2009-08-17 6 views
1

Некоторые из моих пользователей сообщают, что следующий код может поднять UnicodeDecodeError, если имя хоста содержит символы, отличные от ascii (однако я не смог реплицировать это на своей машине с Windows Vista) :UnicodeDecodeError при использовании socket.gethostname() result

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

последняя часть TRACEBACK является:

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) 

Любые идеи о том, почему и как это предотвратить?

(Исключение происходит с Python 2.5 на Windows XP)

ответ

0

Да, если либо имя хоста или имя_директории является строкой Юникода, это, вероятно, даст вам эту ошибку. Лучшее решение, как правило, заключается в том, что оба являются unicode, а не только одним из них.

+0

Так как же я могу это сделать? –

+0

Вы декодируете закодированную строку с "thestring" .decode ('encoding').Какая из строк является строкой и которая является юникодом, вам придется отлаживать, чтобы понять, то же самое с тем, какую кодировку использовать, я не знаю, что вам нужно проверять. –

0

Вам нужна уникальная строка на основе имени хоста, но в ней есть символы Unicode. Существует множество способов уменьшить строку Unicode до строки ascii, в зависимости от того, как вы хотите иметь дело с символами, отличными от ascii. Вот один:

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

Это заменит все символы не-ASCII со знаком вопроса, а затем измените те, чтобы подчеркнуть (так как файловые системы не любят вопросы знаков в именах файлов).

+0

Нед, спасибо. Я не понимаю, почему *, я получаю это исключение: почему декодер os.path.join с кодеком ascii? Я добавил трассировку к моему вопросу (должен был сделать это сразу, конечно, извините). –

0

Я не думаю, что есть проблема с фактическим кодом, который вы отправили, даже если socket.gethostname() возвращает объект unicode. Там будет проблемой при попытке использовать name таким образом, что он превращается в строку первой:

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) 

Вы можете увидеть, что str(name) вызывает исключение, что вы видите, но все выглядит нормально до этого момента , Что вы делаете с name, как только вы его построили?

+0

Это os.path.join, похоже, бросает исключение, это будет четвертая строка в вашем примере кода. Я добавил трассировку к моему вопросу (должен был сделать это сразу, конечно, извините). –

1

Я не думаю, что gethostname() обязательно дает вам объект unicode. Это может быть имя каталога lockfile. Независимо от того, одна из них является стандартной строкой с символом не ASCII (выше 127), а другая является строкой unicode.

Проблема в том, что функция соединения в модуле ntpath (модуль Python использует для os.path в Windows) пытается присоединиться к приведенным аргументам. Это заставляет 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.

Вы можете обойти это, используя сначала преобразование аргументов для объединения() в стандартные строки, как предлагают другие ответы. В качестве альтернативы вы можете сначала конвертировать все в Юникод. Если для декодирования задано определенное кодирование(), высокие байты могут быть преобразованы в unicode.

Например:

>> '\xff'.decode('latin-1') 
u'\xff' 
Смежные вопросы