使用socket.gethostname()结果时出现UnicodeDecodeError

1 投票
4 回答
2599 浏览
提问于 2025-04-15 13:39

我的一些用户反映,下面的代码在主机名包含非ASCII字符时,可能会引发UnicodeDecodeError错误(不过我在我的Windows Vista机器上没有遇到这个问题):

    self.path = path
    self.lock_file = os.path.abspath(path) + ".lock"
    self.hostname = socket.gethostname()
    self.pid = os.getpid()
    dirname = os.path.dirname(self.lock_file)
    self.unique_name = os.path.join(dirname, "%s.%s" % (self.hostname, self.pid))

错误追踪的最后一部分是:

    File "taskcoachlib\thirdparty\lockfile\lockfile.pyo", line 537, in FileLock
    File "taskcoachlib\thirdparty\lockfile\lockfile.pyo", line 296, in __init__
    File "taskcoachlib\thirdparty\lockfile\lockfile.pyo", line 175, in __init__
    File "ntpath.pyo", line 102, in join
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xcf in position 7: ordinal not in range(128)

有没有人知道为什么会这样,以及如何避免这个问题呢?

(这个错误在Windows XP上的Python 2.5中出现)

4 个回答

0

你想要一个基于主机名的独特字符串,但里面有一些Unicode字符。处理这些Unicode字符串变成ASCII字符串的方法有很多,具体取决于你想怎么处理那些不是ASCII的字符。这里有一种方法:

self.hostname = socket.gethostname().encode('ascii', 'replace').replace('?', '_')

这个方法会把所有不是ASCII的字符替换成问号,然后再把问号换成下划线(因为文件系统不喜欢文件名里有问号)。

0

是的,如果主机名或者目录名是Unicode字符串,就很可能会出现这个错误。最好的解决办法通常是确保这两个都是Unicode字符串,而不仅仅是其中一个。

1

我觉得 gethostname() 不一定会给你一个 Unicode 对象。它可能是锁文件的目录名。无论如何,其中一个是包含非 ASCII 字符(大于 127)的普通字符串,另一个是 Unicode 字符串。

问题在于 ntpath 模块中的 join 函数(Python 在 Windows 上使用 os.path 的模块)试图将给定的参数连接起来。这导致 Python 尝试将普通字符串部分转换为 Unicode。在你的情况下,那个非 Unicode 字符串似乎包含了一个非 ASCII 字符。这种情况无法可靠地转换为 Unicode,所以 Python 报错了。

触发这个问题的一个简单方法是:

>> from ntpath import join
>> join(u'abc', '\xff')
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)

/home/msmits/<ipython console> in <module>()

/usr/lib64/python2.6/ntpath.pyc in join(a, *p)
    106                     path += b
    107                 else:
--> 108                     path += "\\" + b
    109             else:
    110                 # path is not empty and does not end with a backslash,

错误追踪信息显示了 ntpath.py 中出问题的那一行。

你可以通过先将 join() 的参数转换为普通字符串来解决这个问题,正如其他答案所建议的那样。或者你也可以先将所有内容转换为 Unicode。如果给 decode() 指定了特定的编码,高位字节可以转换为 Unicode。

例如:

>> '\xff'.decode('latin-1')
u'\xff'

撰写回答