2

当设置了非拉丁语言环境时,IOError.strerror对我来说在 Python 2.7 中变为非 Unicode:

import locale

locale.setlocale(locale.LC_ALL, '')
print locale.getlocale(locale.LC_MESSAGES)

try:
    open('/asdasd', 'w')
except IOError as e:
    print e.strerror
    print repr(e.strerror)
    print unicode(e) # boom

跑步:

LANG=fr_FR.utf8 python test.py

输出:

('fr_FR', 'UTF-8')
Permission non accordée
'Permission non accord\xc3\xa9e'
Traceback (most recent call last):
  File "test.py", line 11, in <module>
    print unicode(e)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 32: ordinal not in range(128)

看起来操作系统错误消息是按strerror原样存储的,而不是先转换为 Unicode。这可以在不手动解码的情况下解决Exception吗?

4

2 回答 2

2

我不确定这会是一个很大的答案,但是:

Python 2 有一些地方(例外就是其中之一)“文本”和“字节”之间的良好区别并没有明确区分。实际上,在Python 2中,我见过的异常​​中的每个字符串都是str, 或bytes. (并不是说自定义库不能 return unicode,而是标准 Python 的东西不会。)因此,您将系统错误视为str/ bytes。您可以通过将最后一行 (the # boom) 更改为:

print unicode(str(e), 'utf-8')

或者,如我所愿,

print str(e).decode('utf-8')

现在,这'utf-8'是一个神奇的常数:它必须匹配语言环境(对于fr_FR.utf8,它确实如此。对于其他非 UTF-8 语言环境,它可能不会。)locale.getpreferredencoding(),我相信,会给你正确的答案,因此:

print str(e).decode(locale.getpreferredencoding())

隧道尽头有光:在Python 3中,您发布的代码应该¹ Just Work。(带有较小的典型 Py3k 更改 -print()是一个函数,并且unicode需要是str。)

¹我可以让它与 fr_FR.utf-8 一起使用,但不是 fr_FR.ISO-8859-1。不知道为什么。后一种编码适用于 Python 2。Python 3 使用我提到的修改运行,但似乎完全去掉了重音。

于 2013-08-23T23:43:20.803 回答
-1

终于想通了:

默认情况下,Python 2ascii用作系统编码(请参阅 参考资料sys.getdefaultencoding)。

不幸的是没有(更准确地说,它被从模块中setdefaultencoding删除),所以我使用的解决方案如下:syssite.py

import locale
import sys

reload(sys)  # reload sys so sys.setdefaultencoding is available again
sys.setdefaultencoding('utf8')

locale.setlocale(locale.LC_ALL, '')

try:
    open('/asdasd', 'w')
except IOError as e:
    print unicode(e)
于 2013-08-24T06:50:54.783 回答