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: must be str, not bytes
p = subprocess.Popen(["demo.exe"],stdout = subprocess.PIPE, stderr= subprocess.PIPE)# 轮询新输出的过程直到完成为真:nextline = p.stdout.readline()if nextline == '' and p.poll() != None:休息sys.stdout.write(下一行)sys.stdout.flush()输出 = 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
).
- 您可以使用
bytes('h€llo', 'utf-8')
将str
转换为bytes
;这应该产生b'H\xe2\x82\xacllo'
.请注意如何将一个字符转换为三个字节. - 您可以使用
b'H\xe2\x82\xacllo'.decode('utf-8')
将bytes
转换为str
.
当然,在您的情况下,UTF-8 可能不是正确的字符集,因此请确保使用正确的.
在您的特定代码段中,nextline
的类型为 bytes
,而不是 str
,从 subprocess
读取 stdout
和 stdin
在 Python 3 中从 str
更改为字节
.这是因为 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''
因为:
另见 Python 3ChangeLog、PEP 358 和 PEP 3112.
<小时>1 有一些巧妙的技巧你可以用 ASCII 来做,而你用多字节字符集却做不到;最著名的例子是xor with space to switch case"(例如 chr(ord('a') ^ ord(' ')) == 'A'
)和将第 6 位设置为创建一个控制字符"(例如 ord('\t') + ord('@') == ord('I')
).ASCII 是在对单个位进行操作对性能影响不可忽视的时代设计的.
2 是的,你可以使用函数注解,但它是一个比较新的功能,很少使用.
I was looking for a way to run an external process from python script and print its stdout messages during the execution.
The code below works, but prints no stdout output during runtime. When it exits I am getting the following error:
sys.stdout.write(nextline) TypeError:must be str,not 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
I am using python 3.3.2
Python 3 handles strings a bit different. Originally there was just one type for
strings: str
. When unicode gained traction in the '90s the new unicode
type
was added to handle Unicode without breaking pre-existing code1. This is
effectively the same as str
but with multibyte support.
In Python 3 there are two different types:
- The
bytes
type. This is just a sequence of bytes, Python doesn't know anything about how to interpret this as characters. - The
str
type. This is also a sequence of bytes, but Python knows how to interpret those bytes as characters. - The separate
unicode
type was dropped.str
now supports unicode.
In Python 2 implicitly assuming an encoding could cause a lot of problems; you
could end up using the wrong encoding, or the data may not have an encoding at
all (e.g. it’s a PNG image).
Explicitly telling Python which encoding to use (or explicitly telling it to
guess) is often a lot better and much more in line with the "Python philosophy"
of "explicit is better than implicit".
This change is incompatible with Python 2 as many return values have changed,
leading to subtle problems like this one; it's probably the main reason why
Python 3 adoption has been so slow. Since Python doesn't have static typing2
it's impossible to change this automatically with a script (such as the bundled
2to3
).
- You can convert
str
tobytes
withbytes('h€llo', 'utf-8')
; this should produceb'H\xe2\x82\xacllo'
. Note how one character was converted to three bytes. - You can convert
bytes
tostr
withb'H\xe2\x82\xacllo'.decode('utf-8')
.
Of course, UTF-8 may not be the correct character set in your case, so be sure to use the correct one.
In your specific piece of code, nextline
is of type bytes
, not str
,
reading stdout
and stdin
from subprocess
changed in Python 3 from str
to
bytes
. This is because Python can't be sure which encoding this uses. It
probably uses the same as sys.stdin.encoding
(the encoding of your system),
but it can't be sure.
You need to replace:
sys.stdout.write(nextline)
with:
sys.stdout.write(nextline.decode('utf-8'))
or maybe:
sys.stdout.write(nextline.decode(sys.stdout.encoding))
You will also need to modify if nextline == ''
to if nextline == b''
since:
>>> '' == b''
False
Also see the Python 3 ChangeLog, PEP 358, and PEP 3112.
1 There are some neat tricks you can do with ASCII that you can't do with multibyte character sets; the most famous example is the "xor with space to switch case" (e.g. chr(ord('a') ^ ord(' ')) == 'A'
) and "set 6th bit to make a control character" (e.g. ord('\t') + ord('@') == ord('I')
). ASCII was designed in a time when manipulating individual bits was an operation with a non-negligible performance impact.
2 Yes, you can use function annotations, but it's a comparatively new feature and little used.
这篇关于Python 3 TypeError:必须是 str,而不是 sys.stdout.write() 的字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!