要将字节序列解释为文本,您必须知道对应字符编码:
unicode_text = bytestring.decode(character_encoding)
例子:
>>> b'\xc2\xb5'.decode('utf-8')
'µ'
ls命令可能产生无法解释为文本的输出。文件名在Unix上可以是除斜杠b'/'和零之外的任何字节序列b“\0”:
>>> open(bytes(range(0x100)).translate(None, b'\0/'), 'w').close()
尝试使用utf-8编码解码此类字节汤会引发UnicodeDecodeError。
可能会更糟。解码可能会无声地失败并产生mojibake如果使用错误的不兼容编码:
>>> '—'.encode('utf-8').decode('cp1252')
'—'
数据已损坏,但您的程序仍然没有意识到故障已发生。
通常,要使用的字符编码不会嵌入字节序列本身。你必须在乐队外传达这些信息。某些结果比其他结果更有可能,因此存在可以猜测字符编码的chardet模块。一个Python脚本可以在不同的地方使用多个字符编码。
ls输出可以使用os.fsdecode()转换为Python字符串即使对于不可编码的函数也会成功文件名(它使用上的sys.getfilesystemencoding()和surrogateescape错误处理程序Unix):
import os
import subprocess
output = os.fsdecode(subprocess.check_output('ls'))
要获取原始字节,可以使用os.fencoder()。
如果传递universal_newlines=True参数,则子流程使用locale.getpreferredencoding(False)以解码字节,例如,它可以是Windows上的cp1252。
为了动态解码字节流,io.TextIOWrapper()例如。
不同的命令可能使用不同的字符编码例如dir内部命令(cmd)的输出可以使用cp437。解码其输出,可以显式传递编码(Python 3.6+):
output = subprocess.check_output('dir', shell=True, encoding='cp437')
文件名可能不同于os.listdir()(它使用WindowsUnicode API),例如,“\xb6”可以替换为“\x14”-Python的cp437编解码器将b'\x14'映射到控制字符U+0014,而不是U+00B6(¶)。要支持具有任意Unicode字符的文件名,请参阅将可能包含非ASCII Unicode字符的PowerShell输出解码为Python字符串