我一直在寻找一种从python脚本运行外部进程的方法,并在执行期间打印其stdout消息.
下面的代码可以工作,但在运行时打印没有stdout输出.当它退出时,我收到以下错误:
sys.stdout.write(nextline)TypeError:必须是str,而不是bytes
p = subprocess.Popen(["demo.exe"],stdout = subprocess.PIPE, stderr= subprocess.PIPE)
# Poll process for new output until finished
while True:
nextline = p.stdout.readline()
if nextline == '' and p.poll() != None:
break
sys.stdout.write(nextline)
sys.stdout.flush()
output = p.communicate()[0]
exitCode = p.returncode
Run Code Online (Sandbox Code Playgroud)
我使用的是python 3.3.2
Mar*_*oij 95
Python 3处理字符串有点不同.最初只有一种类型的字符串:str
.当unicode在90年代获得牵引力时,新unicode
类型被添加到处理Unicode而不破坏预先存在的代码1.这实际上str
与多字节支持相同.
在Python 3中有两种不同的类型:
bytes
类型.这只是一个字节序列,Python不知道如何将其解释为字符.str
类型.这也是一个字节序列,但Python知道如何将这些字节解释为字符.unicode
类型被删除.str
现在支持unicode.在Python 2中隐式假设编码可能会导致很多问题; 您可能最终使用错误的编码,或者数据可能根本没有编码(例如,它是PNG图像).
明确地告诉Python使用哪种编码(或明确地告诉它猜测)通常要好得多,并且更符合" 显式优于隐式 " 的"Python哲学".
这种变化与Python 2不兼容,因为许多返回值已经改变,导致像这样的微妙问题; 这可能是Python 3采用速度如此之慢的主要原因.由于Python没有静态类型2,
因此无法使用脚本(例如捆绑2to3
)自动更改此内容
.
str
到bytes
使用bytes('h€llo', 'utf-8')
; 这应该产生b'H\xe2\x82\xacllo'
.请注意一个字符如何转换为三个字节.bytes
到str
使用 b'H\xe2\x82\xacllo'.decode('utf-8')
.当然,在您的情况下,UTF-8可能不是正确的字符集,因此请务必使用正确的字符集.
在特定的一段代码,nextline
是一个类型bytes
,而不是str
,阅读stdout
以及stdin
从subprocess
来自在Python 3改str
到
bytes
.这是因为Python无法确定使用哪种编码.它
可能与sys.stdin.encoding
(系统的编码)相同,但不能确定.
你需要替换:
sys.stdout.write(nextline)
Run Code Online (Sandbox Code Playgroud)
有:
sys.stdout.write(nextline.decode('utf-8'))
Run Code Online (Sandbox Code Playgroud)
或者可能:
sys.stdout.write(nextline.decode(sys.stdout.encoding))
Run Code Online (Sandbox Code Playgroud)
您还需要修改if nextline == ''
为if nextline == b''
:
>>> '' == b''
False
Run Code Online (Sandbox Code Playgroud)
另请参阅Python 3 ChangeLog,PEP 358和PEP 3112.
1使用ASCII可以做一些巧妙的技巧,你无法使用多字节字符集; 最着名的例子是"xor with space to switch case"(例如chr(ord('a') ^ ord(' ')) == 'A'
)和"set 6th bit to a control a character"(例如ord('\t') + ord('@') == ord('I')
).ASCII的设计是在操纵单个位是一个具有不可忽略的性能影响的操作的时候.
2是的,您可以使用功能注释,但它是一个相对较新的功能,很少使用.
Woo*_*ble 26
如果你从子进程中获得的字节是使用sys.stdout.encoding
(或兼容的编码,如从输出ASCII的工具读取而你的stdout使用UTF-8)编码接受的答案将正常工作,那么将任意字节写入stdout的正确方法是:
sys.stdout.buffer.write(some_bytes_object)
Run Code Online (Sandbox Code Playgroud)
这将按原样输出字节,而不是试图将它们视为一些文本编码.