Skip to main content
 首页 » 编程设计

Python IOError.strerror 不是 Unicode

2025年05月04日11Terrylee

设置非拉丁语言环境时,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 的情况下解决这个问题?

请您参考如下方法:

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

Python 2 有一些地方(异常(exception)是其中之一)“文本”和“字节”之间的区别不是很清楚。实际上,在 Python 2 中,我见过的异常​​中的每个字符串都是 str 或 bytes。 (并不是说自定义库不能返回 unicode,而是标准的 Python 东西不能。)因此,您将系统错误视为 str/字节。您可以将最后一行(# 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 运行我提到的修改,但似乎只是完全放弃了重音。