Python popen() - communication(str.encode(encoding =“utf-8”,errors =“ignore”))崩溃

时间:2015-10-22 14:33:51

标签: python python-3.x encoding subprocess popen

在Windows上使用Python 3.4.3。

我的脚本在控制台中运行一个小程序,应该得到输出:

import subprocess
p1 = subprocess.Popen([ ... ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
out, err = p1.communicate(str.encode("utf-8"))

这导致正常

  

'UnicodeDecodeError:'charmap'编解码器无法解码位置135中的字节0x9d:字符映射到<未定义>”

现在我想忽略错误:

out, err = p1.communicate(str.encode(encoding="utf-8", errors="ignore"))

这导致了一个更有趣的错误,我发现没有帮助使用谷歌:

  

TypeError:'str'对象的描述符'encode'需要一个参数

所以似乎python甚至不知道str.encode(...)的参数是什么。如果省略错误部分也同样适用。

2 个答案:

答案 0 :(得分:12)

universal_newlines=True启用文字模式。结合stdout=PIPE,它强制解码子进程'在Windows上使用不是utf-8的locale.getpreferredencoding(False)输出。这就是您看到UnicodeDecodeError

的原因

阅读子流程'输出使用utf-8编码,删除universal_newlines=True

#!/usr/bin/env python3
from subprocess import Popen, PIPE

with Popen(r'C:\path\to\program.exe "arg 1" "arg 2"',
           stdout=PIPE, stderr=PIPE) as p:
    output, errors = p.communicate()
lines = output.decode('utf-8').splitlines()

str.encode("utf-8")相当于"utf-8".encode()。除非您设置.communicate()并且子进程期望stdin=PIPE bytestring作为输入,否则无法将其传递给b'utf-8'

str.encode(encoding="utf-8", errors="ignore)的格式为klass.method(**kwargs).encode()方法需要self(字符串对象),这就是您看到TypeError的原因。

>>> str.encode("abc", encoding="utf-8", errors="ignore") #XXX don't do it
b'abc'
>>> "abc".encode(encoding="utf-8", errors="ignore")
b'abc'

如果没有充分理由,请勿使用klass.method(obj)代替obj.method()

答案 1 :(得分:2)

你不应该在课堂上调用In [1]: print str.find.__doc__ S.find(sub [,start [,end]]) -> int Return the lowest index in S where substring sub is found, such that sub is contained within S[start:end]. Optional arguments start and end are interpreted as in slice notation. Return -1 on failure. 。您可能想要做的是像

.encode()

您获得的错误消息意味着p1.communicate("FOOBAR".encode("utf-8")) 函数无需编码,因为您在类上调用它,而不是在实例上调用(然后将其作为encode()传递参数self)。