繁体   English   中英

Python 3 TypeError:必须为str,而不是sys.stdout.write()的字节

[英]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 )自动更改此类型。

  • 您可以转换strbytesbytes('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读取stdoutstdin 这是因为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 ChangeLogPEP 358PEP 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM