在 Popen 生成器中处理特殊字符(解码)
Handling special characters (decoding) in a Popen generator
上下文
我有一个生成器,它不断输出来自特定命令的每一行(参见下面的代码片段,代码取自 here)。
def execute(cmd):
popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, universal_newlines=True)
for stdoutLine in iter(popen.stdout.readline, ""):
yield stdoutLine.rstrip('\r|\n')
问题
问题是,stdout 行可能包含 cp1252 无法处理的特殊字符。 (请参阅下面的多条错误消息,每条都来自不同的测试)
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 6210: character maps to <undefined>
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 3691: character maps to <undefined>
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 6228: character maps to <undefined>
问题
我应该如何处理这些特殊字符?
解决方法很简单:如果没有必要,不要解码标准输出。
我的解决方案是向执行函数添加一个参数,该参数确定生成器是否会生成已解码的字符串或未修改的字节。
def execute(cmd, decode=False):
popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, universal_newlines=decode)
for stdoutLine in iter(popen.stdout.readline, ""):
if decode:
yield stdoutLine.rstrip('\r|\n')
else:
yield stdoutLine.rstrip(b'\r|\n')
因此,当我知道我正在执行的命令将 return 个 ASCII 字符并且需要解码的字符串时,我会传递 decode=True
个参数。
上下文
我有一个生成器,它不断输出来自特定命令的每一行(参见下面的代码片段,代码取自 here)。
def execute(cmd):
popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, universal_newlines=True)
for stdoutLine in iter(popen.stdout.readline, ""):
yield stdoutLine.rstrip('\r|\n')
问题
问题是,stdout 行可能包含 cp1252 无法处理的特殊字符。 (请参阅下面的多条错误消息,每条都来自不同的测试)
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 6210: character maps to <undefined>
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 3691: character maps to <undefined>
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 6228: character maps to <undefined>
问题
我应该如何处理这些特殊字符?
解决方法很简单:如果没有必要,不要解码标准输出。
我的解决方案是向执行函数添加一个参数,该参数确定生成器是否会生成已解码的字符串或未修改的字节。
def execute(cmd, decode=False):
popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, universal_newlines=decode)
for stdoutLine in iter(popen.stdout.readline, ""):
if decode:
yield stdoutLine.rstrip('\r|\n')
else:
yield stdoutLine.rstrip(b'\r|\n')
因此,当我知道我正在执行的命令将 return 个 ASCII 字符并且需要解码的字符串时,我会传递 decode=True
个参数。