UnicodeDecodeError when using socket.gethostname() result

三世轮回 提交于 2020-01-24 20:08:23

问题


Some of my users report that the following code may raise a UnicodeDecodeError when the hostname contains non-ascii characters (however I haven't been able to replicate this on my Windows Vista machine):

    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))

The last part of the traceback is:

    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)

Any ideas on why and how to prevent it?

(The exception occurs with Python 2.5 on Windows XP)


回答1:


I don't think gethostname() is necessarily giving you a unicode object. It could be the directory name of lockfile. Regardless, one of them is a standard string with a non-ASCII (higher than 127) char in it and the other is a unicode string.

The problem is that the join function in the ntpath module (the module Python uses for os.path on Windows) attempts join the arguments given. This causes Python to try to convert the normal string parts to unicode. In your case the non-unicode string appears to have a non-ASCII character. This can't be reliably converted to unicode, so Python raises the exception.

A simpler way to trigger the problem:

>> 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,

The traceback shows the problem line in ntpath.py.

You could work around this by using converting the args to join() to standard strings first as other answers suggest. Alternatively you could convert everything to unicode first. If a specific encoding is given to decode() high bytes can be converted to unicode.

For example:

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



回答2:


Yes, if either the hostname or the dirname is a unicode string, it is likely to give you that error. The best solution is typically to make sure both are unicode, and not just one of them.




回答3:


You want a unique string based on the hostname, but it's got Unicode characters in it. There are a variety of ways to reduce a Unicode string to an ascii string, depending on how you want to deal with non-ascii characters. Here's one:

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

This will replace all non-ascii characters with a question mark, then change those to underscore (since file systems don't like questions marks in file names).




回答4:


I don't think that there is a problem with the actual code that you've posted, even if socket.gethostname() returns a unicode object. There will be a problem when you attempt to use name such that it is converted to a string first:

import os
hostname = u'\u1306blah'
pid = os.getpid()
name = os.path.join(os.path.dirname('/tmp/blah.lock'), "%s.%s" % (hostname, pid))

>>> type(name)
<type 'unicode'>

>>> name
u'/tmp/\u1306blah.28292'

>>> print name
/tmp/ጆblah.29032

>>> str(name)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u1306' in position 5: ordinal not in range(128)

You can see that str(name) raises the exception that you're seeing, but everything looks OK up until that point. What are you doing with name once you've constructed it?



来源:https://stackoverflow.com/questions/1290601/unicodedecodeerror-when-using-socket-gethostname-result

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!