如何解决Python "WindowsError信息未正确编码"问题?

4 投票
3 回答
5150 浏览
提问于 2025-04-15 21:46

当Python抛出WindowsError时,错误信息的编码总是和操作系统的编码方式一致,这就很麻烦。例如:

import os
os.remove('does_not_exist.file')

好吧,这里我们遇到了一个异常:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
WindowsError: [Error 2] 系統找不到指定的檔案。: 'does_not_exist.file'

因为我的Windows7是繁体中文,所以我收到的默认错误信息是以big5编码(也叫CP950)显示的。

>>> try:
...     os.remove('abc.file')
... except WindowsError, value:
...     print value.args
...
(2, '\xa8t\xb2\xce\xa7\xe4\xa4\xa3\xa8\xec\xab\xfc\xa9w\xaa\xba\xc0\xc9\xae\xd7\xa1C')
>>>

如你所见,错误信息不是Unicode编码,所以当我尝试打印出来时,就会出现另一个编码错误。这就是问题所在,可以在Python的问题列表中找到这个情况: http://bugs.python.org/issue1754

问题是,如何解决这个问题?如何获取WindowsError的本地编码?我使用的Python版本是2.6。

谢谢。

3 个回答

0

sys.getfilesystemencoding() 可以帮你找到文件系统的编码方式。

import os, sys
try:
    os.delete('nosuchfile.txt')
except WindowsError, ex:
    enc = sys.getfilesystemencoding()
    print (u"%s: %s" % (ex.strerror, ex.filename.decode(enc))).encode(enc)

如果你不是为了在控制台上打印内容,可能想把最终的编码改成 'utf-8'。

0

这只是同样错误信息的repr()字符串。因为你的控制台已经支持cp950编码,所以只需要打印你想要的部分就可以了。在我重新配置我的控制台使用cp950后,这在我的系统上是可以正常工作的。我必须明确地抛出错误信息,因为我的系统是英文的,而不是中文:

>>> try:
...     raise WindowsError(2,'系統找不到指定的檔案。')
... except WindowsError, value:
...     print value.args
...
(2, '\xa8t\xb2\xce\xa7\xe4\xa4\xa3\xa8\xec\xab\xfc\xa9w\xaa\xba\xc0\xc9\xae\xd7\xa1C')
>>> try:
...     raise WindowsError(2,'系統找不到指定的檔案。')
... except WindowsError, value:
...     print value.args[1]
...
系統找不到指定的檔案。

另外,可以使用Python 3.X版本。它会根据控制台的编码打印repr()。下面是一个例子:

Python 2.6.5 (r265:79096, Mar 19 2010, 21:48:26) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> '系統找不到指定的檔案。'
'\xa8t\xb2\xce\xa7\xe4\xa4\xa3\xa8\xec\xab\xfc\xa9w\xaa\xba\xc0\xc9\xae\xd7\xa1C'

Python 3.1.2 (r312:79149, Mar 21 2010, 00:41:52) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> '系統找不到指定的檔案。'
'系統找不到指定的檔案。'
4

我们在俄文版的Windows系统中也遇到了同样的问题:默认语言的编码是cp1251,但是Windows控制台的默认编码却是cp866

>>> import sys
>>> print sys.stdout.encoding
cp866
>>> import locale
>>> print locale.getdefaultlocale()
('ru_RU', 'cp1251')

解决办法是用默认语言的编码来解码Windows消息:

>>> try:
...     os.remove('abc.file')
... except WindowsError, err:
...     print err.args[1].decode(locale.getdefaultlocale()[1])
...

坏消息是,你仍然不能在logging.error()中使用exc_info=True

撰写回答