系统:python 3.4.2 on linux。
我正在开发一个 django 应用程序(无关紧要),我遇到了它抛出的问题
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
当 print 被调用时 (!)。经过相当多的挖掘,我发现我应该检查一下
>>> sys.getdefaultencoding()
'utf-8'
但正如预期的那样,utf8。我还注意到 os.path.exists
在与 unicode 字符串一起使用时会抛出相同的异常。所以我查了一下
>>> sys.getfilesystemencoding()
'ascii'
当我使用 LANG=en_US.UTF-8
时,问题消失了。我现在明白为什么 os.path.exists
有问题了。但我完全不知道为什么 print
语句会受到 filesystem 设置的影响。我缺少第三个设置吗?或者它只是假设 LANG
环境对所有内容都是可信的?
另外...我不明白这里的推理。 LANG
没有说明文件名支持什么编码。这与此无关。它是为当前环境单独设置的,而不是为文件系统设置的。为什么 python 对文件系统文件名使用此设置?它使应用程序非常脆弱,因为在 LANG
未设置或设置为 C
的环境中运行时,所有文件操作都会中断(这并不罕见,尤其是当 web-应用程序以 root 或专门为守护进程创建的新用户运行。
测试代码(不需要实际的 unicode 输入来避免终端编码陷阱):
x=b'\xc4\x8c\xc5\xbd'
y=x.decode('utf-8')
print(y)
问题:
- 是否有一种良好且被接受的方法可以使应用程序对
LANG
设置具有鲁棒性? - 是否有任何实际理由可以从环境而不是文件系统驱动程序中猜测文件系统功能?
- 为什么
print
会受到影响?
最佳答案
LANG
用于确定您的语言环境;如果您没有设置特定的 LC_
变量,则 LANG
变量将用作默认值。
文件系统编码由 LC_CTYPE
variable 决定,但如果您没有专门设置该变量,则会使用 LANG
环境变量。
打印使用 sys.stdout
,这是一个配置有您的终端使用的编解码器的文本文件。您的终端设置也是特定于区域设置的;您的 LANG
变量应该真正反射(reflect)您的终端设置的语言环境。如果那是 UTF-8,您需要确保您的 LANG
变量反射(reflect)了这一点。 sys.stdout
使用 locale.getpreferredencoding(False)
(就像所有没有显式编码集打开的文本流一样)和在 POSIX 系统上也会使用 LC_CTYPE
。
关于Python 'ascii' 打印语句编码问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27448111/