由于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'bytes'
请注意,参数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程序?使用示例是将路径传递给使用其他语言环境的用户的文件。
答案 0 :(得分:9)
请注意,错误是UnicodeEncodeError
而不是UnicodeDecodeError
。 Python保留了在命令行上传递的确切字节(通过PEP 383 surrogateescape
错误处理程序),但这些字节不是有效的UTF-8,因此无法编码为写入控制台。< / p>
处理此问题的最佳方法是使用正确编码的应用程序级别知识来重新解释应用程序内的命令行参数,如以下示例代码所示:
$ 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.1 ,os.fsencode(sys.argv[1])
的等效构造为sys.argv[1].encode(sys.getfilesystemencoding(), 'surrogateescape')
编辑2013年2月:更新了Python 3.2+,并避免假设Python自动检测“UTF-8”作为命令行编码
答案 1 :(得分:2)
你可以这样做:
sys.argv[1].encode()
或者,如果您知道编码将其用作参数或致电bytes(sys.argv[1], 'latin-1')
。
两者都应该给你一个unicode字符串的字节表示。
默认情况下,Python3使用UTF-8。