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

ima*_*hat 61 python subprocess popen

有人可以解释为什么我想要的结果,"嗨",前面有一个字母'b',后跟一个换行符?

我使用的是Python 3.3

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

如果我用python 2.7运行它,则不会出现这个额外的'b'

zig*_*igg 72

b表明您拥有的是bytes,这是一个字节的二进制序列,而不是Unicode字符的字符串.子进程输出字节,而不是字符,这communicate()就是返回的内容.

bytes类型不是直接print()能,所以你正在显示reprbytes你.如果您知道从子进程接收的字节的编码,则可以使用decode()它们将它们转换为可打印的str:

>>> print(b'hi\n'.decode('ascii'))
hi
Run Code Online (Sandbox Code Playgroud)

当然,这个特定示例仅在您实际从子进程接收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…
Run Code Online (Sandbox Code Playgroud)

换行符是echo hi输出内容的一部分. echo的工作是输出你传递的参数,然后输出换行符.如果您对进程输出周围的空白不感兴趣,可以这样使用strip():

>>> b'hi\n'.strip()
b'hi'
Run Code Online (Sandbox Code Playgroud)

  • 我会回答自己,有一个名为`universal_newlines`的神秘名称选项会导致`Popen`对象接受并返回文本字符串. (9认同)
  • @PavelŠimerda虽然os.popen返回文本字符串,但显然它们对于非ascii字符的解码不正确,至少在Windows上是这样.例如,运行`check_output("dir")`,从输出中提取文件名,然后尝试使用`open`访问它将失败,如果文件名包含德语变音符号.可能是一个bug. (3认同)

Dan*_*nil 31

如前所述,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
Run Code Online (Sandbox Code Playgroud)

这种方式Popen()将自己替换这些不需要的符号.

  • 如果您想截断终止换行符,您可能需要在“Popen”中同时使用“universal_newlines=True”(以去掉“b”)和结果字符串上的“strip()”。 (7认同)
  • `universal_newlines = True`就像一个魅力.在我的拙见中,这应该是公认的答案...... (5认同)
  • 它会产生额外的空行。 (3认同)

Nec*_*te2 13

默认情况下,echo命令返回换行符

与此比较:

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

对于字符串前面的b,它表示它是一个字节序列,与Python 2.6+中的普通字符串相同

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

  • 你在括号内不需要'\'. (5认同)

Jen*_*ish 7

b是字节表示,\n是echo输出的结果.

以下将仅打印结果数据

import subprocess
print(subprocess.Popen("echo hi", shell=True,stdout=subprocess.PIPE).communicate()[0].decode('utf-8').strip())
Run Code Online (Sandbox Code Playgroud)