在Python中,使用
subprocess.Popen
我们经常需要将外部工具的输出从字节转换为字符串。 我一直没有考虑太多就使用UTF-8,到目前为止还没有遇到问题。 我遇到了一些代码,其中有人使用 ASCII,这让我思考我应该如何知道要使用哪种编码?这重要吗?
对于简单的字符串,它似乎没有什么区别,例如:
>>> subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'], encoding='ASCII')
'4091146\n'
>>> subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'], encoding='utf-8')
'4091146\n'
我知道 UTF-8 是一个更大的字符集,因此“特殊”字符不能编码为 ASCII:
>>> "Büster".encode('utf-8')
b'B\xc3\xbcster'
>>> "Büster".encode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character '\xfc' in position 1: ordinal not in range(128)
我猜编码取决于外部程序,那么我怎么知道要使用哪一个呢? 始终假设 UTF-8 安全吗?
你问了一个关于字符编码和处理外部进程输出的极好的问题。 虽然简单的字符串在 ASCII 或 UTF-8 中可能看起来相同,但选择正确的编码至关重要,以避免处理包含非 ASCII 字符的数据时出现问题。
以下是选择正确编码的方法:
-
查看外部程序的文档: 确定程序输出的编码的最佳位置是其文档。 它应指定使用的默认编码或允许配置它。
-
检查程序的语言环境设置: 如果文档未明确说明,则程序可能会根据其语言环境设置使用默认编码。 可以通过查看
LC_ALL
、LC_CTYPE
或LANG
等环境变量来检查程序的语言环境。 -
从上下文推断: 如果无法从文档或语言环境设置中确定编码,则可能需要根据程序的用途或它处理的数据类型来推断它。 例如,如果程序处理来自多语言源的文本,则很可能使用 UTF-8。
-
始终假设 UTF-8 安全吗? 虽然 UTF-8 正在成为一种越来越普遍的默认编码,但假设它并不总是安全的。 某些程序可能仍在使用旧版编码,并且假设 UTF-8 可能会导致数据损坏或解释错误。
如果无法确定要使用的正确编码,该怎么办:
-
尝试使用
chardet
库: Python 的chardet
库可以分析字节流并估计最可能的编码。 这并不总是准确的,但可以作为一个有用的起点。 ```python import chardetoutput_bytes = subprocess.check_output(['some_command']) detected_encoding = chardet.detect(output_bytes)['encoding'] output_string = output_bytes.decode(detected_encoding, errors='replace')
`` * **使用
errors='replace'进行解码:** 将
errors参数设置为
'replace'` 将导致解码器用特殊字符(例如 Unicode 替换字符 (�))替换无法解码的字符。 这可以帮助防止的程序因编码错误而崩溃,但可能会导致数据丢失。
你的示例:
在你的
git rev-parse
示例中,ASCII 和 UTF-8 都可以正常工作,因为输出(一个简短的提交哈希值)仅包含 ASCII 字符。 但是,如果
git
命令的输出包含非 ASCII 字符(例如,提交消息中的作者姓名),则使用 ASCII 将失败。
总之,不要想当然地认为编码。 咨询文档、检查语言环境设置或使用编码检测工具来避免将来出现问题。
标签:python,character-encoding From: 63771125