Popen.communicate()が「hi」ではなくb「hi \ n」を返すのはなぜですか?


95

誰かが、私が望む結果「hi」の前に文字「b」があり、その後に改行が続く理由を説明できますか?

私が使用していますのPython 3.3を

>>> import subprocess
>>> print(subprocess.Popen("echo hi", shell=True,
                           stdout=subprocess.PIPE).communicate()[0])
b'hi\n'

この余分な「b」は、Python2.7で実行すると表示されません


1
どのバージョンのPythonを使用していますか?
necrolyte2 2013年

2
'b'についてはわかりませんが、改行は。をecho hi出力するためhi\r\nです。これを回避するには、最後に.strip()を追加するか、同様の修正を行います。
azhrei 2013年

7
ここのcheck_output()代わりに使用できます.communicate()print(subprocess.check_output("echo hi", shell=True, universal_newlines=True), end="")
jfs 2013年

回答:


22

echoコマンドはデフォルトで改行文字を返します

これと比較してください:

print(subprocess.Popen("echo -n hi", \
    shell=True, stdout=subprocess.PIPE).communicate()[0])

文字列の前にあるbについては、Python2.6以降の通常の文字列と同等のバイトシーケンスであることを示しています。

http://docs.python.org/3/reference/lexical_analysis.html#literals


6
括弧内に「\」は必要ありません。
jfs 2015年

95

b何を持っていることであることを示しているbytesバイトのバイナリ列ではなく、Unicode文字の文字列です。文字ではなく出力バイトをサブプロセスするので、それcommunicate()が返されます。

bytesタイプは、直接ではありませんprint()あなたが表示されているので、可能なreprbytesあなたが持っているの。サブプロセスから受け取ったバイトのエンコーディングがわかっている場合は、decode()それらを使用して印刷可能なものに変換できますstr

>>> print(b'hi\n'.decode('ascii'))
hi

もちろん、この特定の例は、実際にサブプロセスからASCIIを受信して​​いる場合にのみ機能します。ASCIIでない場合は、例外が発生します。

>>> print(b'\xff'.decode('ascii'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0…

改行はecho hi出力されたものの一部です。 echoの仕事は、渡したパラメータを出力し、その後に改行を続けることです。プロセス出力を囲む空白に興味がない場合は、次のstrip()ように使用できます。

>>> b'hi\n'.strip()
b'hi'

1
print()関数で、前に「b」を付けずにバイト文字列を出力するにはどうすればよいですか?または、最初にUnicode文字列に変換する必要がありますか?
imagineerThat

os.popenテキスト文字列を返すときsubprocess.Popenに、バイト文字列の代わりにそれらも返すようにする方法があるかどうか知りたいです。
パベルŠimerda

11
私は自分自身に答えますuniversal_newlinesPopenオブジェクトがテキスト文字列を受け入れて返すようにするという暗号名のオプションがあります。
パベルŠimerda

3
@PavelŠimerdaos.popenはテキスト文字列を返しますが、少なくともWindowsでは、ASCII以外の文字に対して正しくデコードされていないようです。たとえば、ファイル名にドイツ語のウムラウトが含まれている場合、実行中check_output("dir")、出力からファイル名を抽出してからアクセスしようとするopenと失敗します。バグかもしれません。
kdb 2015年

60

前に述べたように、echo hi実際には戻りますがhi\n、これは予想される動作です。

しかし、おそらくデータを「正しい」形式で取得し、エンコーディングを処理したくないでしょう。あなたがする必要があるのはそうするためにuniversal_newlines=Trueオプションを渡すsubprocess.Popen()ことです:

>>> import subprocess
>>> print(subprocess.Popen("echo hi",
                           shell=True,
                           stdout=subprocess.PIPE,
                           universal_newlines=True).communicate()[0])
hi

このようPopen()にして、これらの不要なシンボルを自動的に置き換えます。


11
universal_newlines=True魅力のように働いた。私の謙虚な意見では、これは受け入れられた答えであるはずです...
イーサンストライダー2018

3
余分な空の行が生成されます。
LoMaPh

1
終了改行を切り刻む場合は、結果の文字列にin (を取り除くため)とaの両方 が必要になる場合があります。universal_newlines=TruePopenb''strip()
arielf

参考までに、ドキュメントによるuniversal_newlinesと、textパラメータの下位互換性のあるエイリアスになりました。これはより明確ですが、Python3.7以降でのみ使用できます。
ハリーカッツ

動作しないため、余分な空の行が生成されます。Universal_newlinesは削除しません\ n
kol 2320年

8

bはバイト表現で、\ nはエコー出力の結果です。

以下は結果データのみを出力します

import subprocess
print(subprocess.Popen("echo hi", shell=True,stdout=subprocess.PIPE).communicate()[0].decode('utf-8').strip())
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.