【问题标题】:sys.argv as bytes in Python 3ksys.argv 在 Python 3k 中作为字节
【发布时间】:2011-10-22 08:02:17
【问题描述】:

由于 Python 3k 引入了字符串和字节之间的严格区分,数组 sys.argv 中的命令行参数以字符串形式呈现。有时有必要将参数视为字节,例如当传递不需要在 Unix 中采用任何特定字符编码的路径时。

让我们看一个例子。一个简短的 Python 3k 程序argv.py 如下:

import sys

print(sys.argv[1])
print(b'bytes')

当它以python3.1 argv.py français 执行时,它会产生预期的输出:

法语

b'字节'

请注意,参数 français 在我的语言环境编码中。但是,当我们以不同的编码传递参数时,我们会得到一个错误:python3.1 argv.py `echo français|iconv -t latin1`

Traceback (most recent call last):
  File "argv.py", line 3, in <module>
    print(sys.argv[1])
  UnicodeEncodeError: 'utf-8' codec can't encode character '\udce7' in position 4: surrogates not allowed

我们如何通过命令行参数将二进制数据传递给 Python 3k 程序?一个使用示例是将路径传递给使用其他语言环境的用户的文件。

【问题讨论】:

  • 编码问题误导了答案,我建议python3 argv.py `echo -ne "\xff\x80\x00"` 这是«通过命令行参数传递二进制数据»的示例

标签: python string unicode python-3.x


【解决方案1】:

请注意,错误是 UnicodeEncodeError 而不是 UnicodeDecodeError。 Python 保留了在命令行上传递的确切字节(通过 PEP 383 surrogateescape 错误处理程序),但这些字节不是有效的 UTF-8,因此不能被编码为写入控制台。

解决这个问题的最佳方法是使用正确编码的应用程序级知识来重新解释应用程序内的命令行参数,如以下示例代码所示:

$ python3.2 -c "import os, sys; print(os.fsencode(sys.argv[1]).decode('latin-1'))" `echo français|iconv -t latin1`
français

os.fsencode 函数调用反转 Python 在处理命令行参数时自动应用的转换。然后decode('latin-1') 方法调用执行正确的转换以获得正确解码的字符串。

Python 3.2 专门添加了os.fsencode 以使此类问题更易于处理。

对于 Python 3.1os.fsencode(sys.argv[1]) 的等效构造是 sys.argv[1].encode(sys.getfilesystemencoding(), 'surrogateescape')

2013 年 2 月编辑:针对 Python 3.2+ 进行了更新,并避免假设 Python 自动检测到“UTF-8”作为命令行编码

【讨论】:

  • 您不能假设语言环境是 UTF-8。因此,您必须使用文件系统编码进行编码: sys.argv[1].encode(sys.getfilesystemencoding(), 'surrogateescape').decode('latin-1')
  • 确实如此。尽管在 Python 3.3 中,使用 os.fsencode 更加容易。我还提交了一个错误,指出 sys.argv 文档实际上应该解释这一点。
【解决方案2】:

你可以这样做:

sys.argv[1].encode() 或者,如果您知道编码,请将其用作参数或调用 bytes(sys.argv[1], 'latin-1')

两者都应该为您提供 unicode 字符串的字节表示。

默认情况下,Python3 使用 UTF-8。

【讨论】:

  • 不,Python 不一定使用 UTF8,它取决于平台。
  • @Lennart Python 3 确实使用 UTF-8 作为默认编码。
  • 不,没那么简单。终端的默认编码不一定是 UTF-8,文件系统的默认编码也不一定。我引用“有一个依赖于平台的默认编码,在 Unixy 平台上可以使用 LANG 环境变量设置(有时也可以使用其他一些特定于平台的与语言环境相关的环境变量)。在许多情况下,但不是全部,系统默认是 UTF-8;你永远不应该指望这个默认值。”事实上,cp1252 是 Windows 上的默认值。 .py 文件的默认值是 UTF8。
  • 不幸的是,@JBernardo 建议的解决方案不起作用,因为 Python 无法将 latin1 字节的法语作为它期望从我的 UTF-8 环境中获得的 UTF-8 字节处理。它无法解释命令行参数(C 中的字节)应该是编码为语言环境编码的字符串的字节。
  • 我同意 Lennart 的观点,它并不那么简单 - 需要反转自动 surrogateescape 过程以获取原始字节,然后可以根据应用程序特定的知识对其进行处理。跨度>
猜你喜欢
  • 1970-01-01
  • 2021-06-18
  • 2017-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-23
相关资源
最近更新 更多