Понимание Unicode в Python и UnicodeDecodeError - PullRequest
2 голосов
/ 23 мая 2011

В Python 2.7 на Mac я печатаю имена файлов, полученные с помощью PlaintextCorpusReader nltk:

infobasecorpus = PlaintextCorpusReader(corpus_root, '.*\.txt')
for fileid in infobasecorpus.fileids():
    print fileid

и получите UnicodeDecodeError: 'ascii', '100316-N1-The \xc2\xa3250bn cost of developing.txt', 14, 15, 'ordinal not in range(128)' из-за символа £ в имени файла.

Как я понимаю, fileid - это строка в кодировке Unicode, которую мне нужно кодировать в кодировку по умолчанию, прежде чем я смогу ее распечатать, а кодировкой по умолчанию является ASCII.

Если я использую print fileid.encode('ascii', 'ignore'), я получаю ту же ошибку.

Если я изменю кодировку по умолчанию, установив encoding = "utf-8" в site.py, (согласно этому совету ) это сработает.

Может кто-нибудь сказать мне: (а) почему encode не удалось (б) почему encoding работает и (c) что я должен делать, если я делаю что-то здесь не так? (Например, это описывает настройку кодировки по умолчанию как «некрасивый хак», который приводит к неправильному использованию строк и созданию глючного кода.)

(Отказ от ответственности: новичок в Python, очень благодарен за ваше терпение, если это очевидно)

=========================================== Обновление для ответа Робу:

Роб, вот полный текст тестового кода:

import sys
import os
from nltk.corpus import PlaintextCorpusReader

corpus_root = '/Users/richlyon/Documents/Filing/Infobase/'
infobasecorpus = PlaintextCorpusReader(corpus_root, '.*\.txt')

for fileid in infobasecorpus.fileids():
    print type(fileid)             # result <type 'str'>
    fileid = fileid.decode('utf8')
    print type(fileid)             # result <type 'unicode'>
    print fileid.encode('ascii')

Я установил кодировку по умолчанию обратно на ascii и запустил ее.

print fileid.encode('ascii') все еще терпит неудачу на £ в имени файла.

=========================================== Последнее обновление на случай, если это кому-нибудь поможет.

Мне нужно было написать:

fileid = fileid.decode('utf8')
print fileid.encode('ascii', 'ignore')

но text = nltk.Text(infobasecorpus.words(fileid)) дросселирует, если на него подается <type 'unicode'> строк, что, кажется, противоречит рекомендации немедленно преобразовать все в unicode перед дальнейшей обработкой.

Но теперь это работает. Спасибо всем, и Робу в частности.

1 Ответ

2 голосов
/ 23 мая 2011

Проверьте тип объекта fileid.Я подозреваю, что не объект Unicode, как вы предлагаете.UnicodeDecodeError повышается из-за неявного декодирования перед кодированием строки для вывода питоном (на print).

Как только строка успешно декодирована (в unicode),затем вы можете распечатать его, явно зашифровав его с помощью кодека, поддерживаемого вашим терминалом.Если ваш терминал поддерживает отображение Unicode, вам может не потребоваться кодировать его перед выводом.

infobasecorpus = PlaintextCorpusReader(corpus_root, '.*\.txt')
for fileid in infobasecorpus.fileids():
    fileid = fileid.decode('utf8') ## fileid is now a unicode object
    print fileid.encode('utf8')

Замените utf8 на то, какое кодирование используется вашей файловой системой (возможно, latin1 в Windows?, Не уверен).

РЕДАКТИРОВАТЬ: Переопределение кодировки по умолчанию для всего сайта считается хаком, так как a) может скрывать проблемы программирования, которые могут означать, что ваш код не переносим при установке Python и b) можетвлияет на другой код, запущенный из той же установки Python.Кроме того, ясное понимание кодирования и декодирования ваших строк облегчает жизнь, когда вы позже вернетесь к своему коду;Вам не нужно помнить, что вы изменили site.py

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...