Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Popen.communicate()引发数据删除错误_Python_Python 3.x_Unicode_Subprocess - Fatal编程技术网

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)