Ell*_*t B 2 python character-encoding
在Python中,subprocess.Popen我们经常需要将外部工具的输出从字节转换为字符串。我一直没有考虑太多就使用UTF-8,到目前为止还没有遇到问题。我遇到了一些代码,其中有人使用 ASCII,这让我思考我应该如何知道要使用哪种编码,这重要吗?
对于简单的字符串,这似乎没有什么区别,例如:
\n>>> subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'], encoding='ASCII')\n'4091146\\n'\n>>> subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'], encoding='utf-8')\n'4091146\\n'\nRun Code Online (Sandbox Code Playgroud)\n据我所知,UTF-8是一个更大的字符集,因此“特殊”字符不能编码为ASCII:
\n>>> "B\xc3\xbcster".encode('utf-8')\nb'B\\xc3\\xbcster'\n>>> "B\xc3\xbcster".encode('ascii')\nTraceback (most recent call last):\n File "<stdin>", line 1, in <module>\nUnicodeEncodeError: 'ascii' codec can't encode character '\\xfc' in position 1: ordinal not in range(128)\nRun Code Online (Sandbox Code Playgroud)\n我猜编码取决于外部程序,那么我怎么知道要使用哪一种呢?始终假设 UTF-8 安全吗?
\n没有“一刀切”的答案。对您的系统有意义的内容对其他系统没有意义。(如果不是这种情况,Python 应该只支持单一编码,你不觉得吗?)
\n在任何计算机上,主要考虑因素是与系统上的其他实用程序保持兼容。如果您的系统是来自黑暗时代的“大铁”大型机,则可能所有内容都需要配置为使用一些可怕的传统 8 位编码(或更糟!)。在频谱的另一端,世界正在朝着 Unicode 和特别是 UTF-8 编码(另请参阅https://utf8everywhere.org/);如果您使用的是相当现代的非 Windows 系统,您locale可能会指出该系统已设置为 UTF-8,然后这就是您应该使用的内容(并且几乎可以肯定 Python 已配置为使用它作为其编码)默认编码;因此您实际上只需要说出text=True而不是明确命名编码)。
剩下的就是 Windows,它通常配置有对其销售地区有意义的任何代码页;在美洲和西欧,这意味着代码页 1252,而在世界其他地区,它意味着其他内容(东欧 1250 或 1251,世界其他地区的各种其他国家或地区特定的代码页);但同样,subprocess您可以直接使用 Python,text=True并让 Python 代表您进行选择。
关键字参数text=True之前被调用过,现在universal_newlines=True仍然有效;真正旧的 Python 3 版本仍然需要您显式编码和解码,当然,在某些情况下您需要或想要使用原始二进制编码来与选定的外部实用程序进行通信。
例子:
\nr = subprocess.run([\'git\', \'rev-parse\', \'--short\', \'HEAD\'],\n text=True, capture_output=True)\nprint(r.stdout) # implicitly uses Python\'s default encoding to decode\n\ns = subprocess.run([\'dd\', \'if=/dev/urandom\', \'bs=32\', \'count=1\'],\n capture_output=True)\nrandom_bytes = s.stdout # not text, no encoding, just raw bytes\n\n# Actually don\'t use Popen when run() can do the job\nfugly = subprocess.Popen([\'cat\', \'/etc/motd\'], text=True)\nstdout, stderr = fugly.communicate()\nfugly.wait() # really, use subprocess.run() instead\n\n# If you specifically want a particular encoding, of course, go for it\nweird = subprocess.run([\'iconv\', \'-t\', \'koi8-u\'],\n stdin=open(\'utf8.txt\'), encoding=\'koi8-u\', capture_output=True)\nRun Code Online (Sandbox Code Playgroud)\n(subprocess.run()替换check_output和朋友,尽管为了方便起见,您当然仍然可以使用它们。无论如何,这些示例中的大多数都确实很折磨,您应该真正使用Python的本机功能而不是外部子进程。)
在处于迁移过程中的系统上,您确实必须单独检查每个实用程序所需的编码,尽管对于 UTF-8 它是方便透明的,而且许多实用程序从未明确适应 UTF-8只会继续工作。问题区域将是排序规则(排序顺序)和 Unicode 标准化等极端情况(na\xc3\xafve 字符串比较不会将序列 U+006F U+0308 视为等同于代码点 U+00F6,即使它们都表示单个字形\xc3\xb6)。
\n通过网络进行通信可能会很麻烦。对于 HTTP,ISO 8859-1(又名 Latin-1)一度被编纂为 HTML 的标准字符集,但现在它是 UTF-8。对于许多网络协议来说,它是未指定的,您只需进行试验即可。涉及文本信息的现代协议应指定一种编码或一种机制,用于显式标记任何文本数据的字符集和编码;MIME 标头最初是为电子邮件指定的,但现在已经应用于其他几种协议,包括 HTTP。电子邮件具有一系列令人困惑的附加编码,可在过去仅支持 7 位 ASCII 的通道上实现完全透明;请注意 MIME 标头中的消息体、消息标头和文件名属性各自有自己的机制。(RFC 2045、2047 和 2231。)
\n| 归档时间: |
|
| 查看次数: |
1530 次 |
| 最近记录: |