[英]Python 3 TypeError: must be str, not bytes with sys.stdout.write()
我一直在寻找一种从python脚本运行外部进程并在执行期间打印其stdout消息的方法。
下面的代码有效,但是在运行时不输出标准输出。 退出时,出现以下错误:
sys.stdout.write(nextline)TypeError:必须为str,而不是字节
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
我正在使用python 3.3.2
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'
。 请注意如何将一个字符转换为三个字节。 b'H\\xe2\\x82\\xacllo'.decode('utf-8')
将bytes
转换为str
。 当然,UTF-8可能不是您所用的正确字符集,因此请确保使用正确的字符集。
在您的特定代码段中, nextline
的类型为bytes
而不是str
,从Python 3中从str
更改为bytes
subprocess
nextline
读取stdout
和stdin
。 这是因为Python无法确定它使用哪种编码。 它可能使用与sys.stdin.encoding
(系统的编码)相同的方式,但是不能确定。
您需要更换:
sys.stdout.write(nextline)
与:
sys.stdout.write(nextline.decode('utf-8'))
或者可能:
sys.stdout.write(nextline.decode(sys.stdout.encoding))
您还需要将if nextline == ''
修改为if nextline == b''
因为:
>>> '' == b''
False
另请参阅Python 3 ChangeLog , PEP 358和PEP 3112 。
1使用ASCII可以完成一些巧妙的技巧,而使用多字节字符集则无法完成这些技巧。 最著名的例子是“用空格进行大小写转换的异或”(例如chr(ord('a') ^ ord(' ')) == 'A'
)和“将第6位设置为控制字符”(例如ord('\\t') + ord('@') == ord('I')
)。 ASCII是在操作单个位的操作对性能造成不可忽略的影响的时候设计的。
2是的,您可以使用功能注释,但这是一个相对较新的功能,很少使用。
如果您使用sys.stdout.encoding
(或兼容的编码,例如从输出ASCII的工具读取且stdout使用UTF-8的兼容编码) sys.stdout.encoding
的字节进行编码,那么可接受的答案会很好用,但是正确的方法是向stdout写入任意字节是:
sys.stdout.buffer.write(some_bytes_object)
这只会按原样输出字节,而不会尝试将它们视为“文本编码”。
为了在Python 3.7.0中写入文件,以下代码有效
f.write(str(YOURFileContent, 'utf-8'))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.