为什么Popen.communicate()返回b'hi \ n'而不是'hi'?


92

有人可以解释为什么我想要的结果“ hi”以字母“ b”开头并以换行符结尾吗?

我正在使用Python 3.3

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

如果我使用python 2.7运行此额外的“ b”,则不会出现


1
您正在使用哪个版本的Python?
Necrolyte2 2013年

2
不确定'b',但是换行符是因为echo hiprints hi\r\n。为避免这种情况,您可以在末尾添加.strip()或类似的修补程序。
2013年

7
您可以使用此处check_output()代替.communicate()print(subprocess.check_output("echo hi", shell=True, universal_newlines=True), end="")
jfs 2013年

Answers:



94

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也可以返回它们,而不是字节字符串。
PavelŠimerda2014年

11
我会回答自己,有一个带有神秘名称的选项,universal_newlines它使Popen对象接受并返回文本字符串。
PavelŠimerda2014年

3
@PavelŠimerda虽然os.popen返回文本字符串,但对于非ascii字符,它们显然被错误地解码,至少在Windows上是如此。例如check_output("dir")open如果文件名包含德语变音符号,则从输出中提取文件名然后尝试使用进行访问将失败。可能是个错误。
kdb 2015年

57

如前所述,echo hi实际上确实会返回return 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像魅力一样运作。在我的拙见中,这应该是公认的答案...
Ethan Strider

3
它产生多余的空行。
LoMaPh

1
您可能需要 universal_newlines=TruePopen(摆脱的b'')和一个strip()上生成的字符串,如果你想砍终止换行符。
arielf

仅供参考,文档universal_newlines现在只是该text参数的向后兼容别名,这更清楚了,但仅在Python 3.7及更高版本中。
哈里·卡茨

它产生多余的空行,因为它不起作用。Universal_newlines不会删除\ n
kol23

8

b是字节表示形式,\ n是回显输出的结果。

以下将仅打印结果数据

import subprocess
print(subprocess.Popen("echo hi", shell=True,stdout=subprocess.PIPE).communicate()[0].decode('utf-8').strip())
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.