Python popen() - 通信( str.encode(encoding="utf-8", errors="ignore") )崩溃

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33283603/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 13:08:32  来源:igfitidea点击:

Python popen() - communicate( str.encode(encoding="utf-8", errors="ignore") ) crashes

pythonpython-3.xencodingsubprocesspopen

提问by user136036

Using Python 3.4.3 on Windows.

在 Windows 上使用 Python 3.4.3。

My script runs a little java program in console, and should get the ouput:

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

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

This leads to a normal

这导致正常

'UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 135: character maps to < undefined>'.

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

Now I want to ignore errors:

现在我想忽略错误:

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

This leads to a more interesting error I found no help for using google:

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

TypeError: descriptor 'encode' of 'str' object needs an argument

类型错误:“str”对象的描述符“编码”需要一个参数

So it seems that python does not even know anymore what the arguments for str.encode(...) are. The same also applies when you leave out the errors part.

所以看起来 python 甚至不再知道 str.encode(...) 的参数是什么。当您省略错误部分时,这同样适用。

采纳答案by jfs

universal_newlines=Trueenables text mode. Combined with stdout=PIPE, it forces decoding of the child process' output using locale.getpreferredencoding(False)that is not utf-8 on Windows. That is why you see UnicodeDecodeError.

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

To read the subprocess' output using utf-8 encoding, drop universal_newlines=True:

要使用 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")is equivalent to "utf-8".encode(). There is no point to pass it to .communicate()unless you set stdin=PIPEand the child process expects b'utf-8'bytestring as an input.

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

str.encode(encoding="utf-8", errors="ignore)has the form klass.method(**kwargs). .encode()method expects self(a string object) that is why you see TypeError.

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'

Do not use klass.method(obj)instead of obj.method()without a good reason.

没有充分的理由不要使用klass.method(obj)代替obj.method()

回答by cemper93

You are not supposed to call .encode()on the class itself. What you probably want to do is something like

你不应该调用.encode()类本身。你可能想要做的是

p1.communicate("FOOBAR".encode("utf-8"))

The error message you're getting means that the encode()function has nothing to encode, since you called it on the class, rather than on an instance (that would then be passed as the selfparameter to encode()).

您收到的错误消息意味着该encode()函数无需编码,因为您是在类上调用它,而不是在实例上调用它(然后将其作为self参数传递给encode())。