为什么Popen.communicate()返回b'hi\n'而不是'hi'?
有人能解释一下为什么我想要的结果“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'就不会出现。
4 个回答
101
之前提到过,echo hi
实际上会返回 hi\n
,这是正常的行为。
不过你可能只是想要以“正确”的格式获取数据,而不想处理编码问题。你只需要在调用 subprocess.Popen()
时加上 universal_newlines=True
这个选项,像这样:
>>> import subprocess
>>> print(subprocess.Popen("echo hi",
shell=True,
stdout=subprocess.PIPE,
universal_newlines=True).communicate()[0])
hi
这样一来,Popen()
就会自动替换掉这些不需要的符号。
122
这里的 b
表示你得到的是 bytes
,也就是一串二进制数据,而不是一串Unicode字符。子进程输出的是字节,而不是字符,所以 communicate()
返回的就是这些字节。
而 bytes
类型不能直接用 print()
打印,所以你看到的是这些字节的 repr
(表示形式)。如果你知道从子进程接收到的字节的编码方式,可以用 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'
28
echo命令默认会返回一个换行符
对比一下这个:
print(subprocess.Popen("echo -n hi", \
shell=True, stdout=subprocess.PIPE).communicate()[0])
至于字符串前面的b,它表示这是一个字节序列,在Python 2.6及以上版本中,这和普通字符串是一样的
http://docs.python.org/3/reference/lexical_analysis.html#literals