Python Popen.communicate()引发数据删除错误
我有以下代码:Python Popen.communicate()引发数据删除错误,python,python-3.x,unicode,subprocess,Python,Python 3.x,Unicode,Subprocess,我有以下代码: def __executeCommand(self, command: str, input: str = None) -> str: p = sub.Popen(command, stdout=sub.PIPE, stderr=sub.PIPE, stdin=sub.PIPE, universal_newlines=True) p.stdin.write(input) output, error = p.communicate() if (
def __executeCommand(self, command: str, input: str = None) -> str:
p = sub.Popen(command, stdout=sub.PIPE, stderr=sub.PIPE, stdin=sub.PIPE, universal_newlines=True)
p.stdin.write(input)
output, error = p.communicate()
if (len(errors) > 0):
raise EnvironmentError("Could not generate the key: " + error)
elif (p.returncode != 0):
raise EnvironmentError("Could not generate the key. Return Value: " + p.returncode)
return output
我在输出行中得到一个UnicodeDecodeError,error=p.communicate()
:
回溯(最近一次呼叫最后一次):
文件“C:\Python34\lib\threading.py”,第921行,在\u bootstrap\u内部
self.run()
文件“C:\Python34\lib\threading.py”,第869行,正在运行
自我目标(*自我参数,**自我参数)
文件“C:\Python34\lib\subprocess.py”,第1170行,在_readerthread中
buffer.append(fh.read())
文件“C:\Python34\lib\encodings\cp1252.py”,第23行,解码
返回编解码器.charmap\u解码(输入、自身错误、解码表)[0]
UnicodeDecodeError:“charmap”编解码器无法解码位置27:字符映射到的字节0x81
我怎样才能解决这个问题 设置
universal\u newlines=true
会导致额外的编码,这是错误的根源
def __executeCommand(self, command: str, input: str = None) -> str:
p = sub.Popen(command, stdout=sub.PIPE, stderr=sub.PIPE, stdin=sub.PIPE)
output, error = p.communicate(input)
if (len(errors) > 0):
raise EnvironmentError("Could not generate the key: " + error)
elif (p.returncode != 0):
raise EnvironmentError("Could not generate the key. Return Value: " + p.returncode)
return output
universal\u newlines=true
根据以下输出进行编码:
python-c'导入区域设置;打印locale.getpreferredencoding()'
Python在期望您的输入与上面的编码匹配时抛出了一个错误,但却以不同的编码处理了一个字节
有关python 3.4的更多信息
universal\u newlines
univeral\u newlines=True
启用文本模式。子流程输出(字节)使用locale.getpreferredencoding(False)
字符编码as进行解码
如果不起作用,请提供命令使用的实际编码。和/或指定错误处理程序,例如errors
参数:
from subprocess import Popen, PIPE
def __executeCommand(self, command: str, input: str = None,
encoding=None, errors='strict') -> str:
text_mode = (encoding is None)
with Popen(command, stdout=PIPE, stderr=PIPE, stdin=PIPE,
universal_newlines=text_mode) as p:
if input is not None and not text_mode:
input = input.encode(encoding, errors) # convert to bytes
output, err = p.communicate(input)
if err or p.returncode != 0:
raise EnvironmentError("Could not generate the key. "
"Error: {}, Return Value: {}".format(
ascii(err), p.returncode))
return output if text_mode else output.decode(encoding, errors)
如果您使用的是Python 3.6或更高版本,则可以通过更改以下行来修复错误:
p = sub.Popen(command, stdout=sub.PIPE, stderr=sub.PIPE, stdin=sub.PIPE, universal_newlines=True)
为此:
p = sub.Popen(command, stdout=sub.PIPE, stderr=sub.PIPE, stdin=sub.PIPE, encoding="utf-8", universal_newlines=True)
我在上面使用了UTF-8,但是您可以用您需要的任何编码替换它。无关:您不需要p.stdin.write(input)
;使用…=p、 通信(输入)
代替。注意:->str
在函数签名中。如果删除universal\u newlines=True
,则子流程
以二进制模式工作,即结果是字节
,而不是str
。您必须手动解码(您需要知道命令使用的字符编码,以解码其输出)。你也必须对输入进行编码。我认为这必须假设在上面一层。无法预先知道每个命令的编码是作为输入还是作为输出返回的。据我所知,类型bytes和类型str之间没有区别。可以选择将输出包装为str(output,locale.getpreferredencode())
。如我所述,包装也可能引发上述错误。请注意,OP使用Python 3:str
(Unicode文本)与字节
类型(二进制类型)非常不同。使用区域设置
编码进行包装不会有帮助,否则通用换行符会起作用。OP应该提供正确的编码和/或使用errors
处理程序(bytestring.decode(encoding,errors)
或通过io.TextIOWrapper(p.stdout,encoding,errors)
)我没有找到正确的编码。。。但是因为只有错误消息包含特殊字符output.decode(encoding,errors='replace')
为我做了这件事。Python应该是一种脚本语言。。。这感觉像是C语言中最糟糕的一种…@ChristopherRoezbek:您将如何用您选择的任何语言实现相同的功能?(可能有一个问题是,将功能打包成一个函数有多合理,但它与Python无关:你可以用任何语言编写FORTRAN)@J.F.Sebastian:很抱歉我感到沮丧,我只是从来没有使用过让我担心这么多事情(编码、换行)的脚本语言,当我只需要简单明了的backtick操作符行为时:运行一个命令,将stdout和stderr作为字符串再次打印到stdout。@ChristophenRoezbek:如果需要“backtick”;使用output=subprocess。检查输出(命令)
。我看不出它与问题或Python有什么关系:如果您使用的是文本;您应该了解编码()。
p = sub.Popen(command, stdout=sub.PIPE, stderr=sub.PIPE, stdin=sub.PIPE, encoding="utf-8", universal_newlines=True)