Понимание Unicode в Python и UnicodeDecodeError

1

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

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 - это строка Юникода, которую мне нужно кодировать по умолчанию, прежде чем я смогу ее распечатать, а по умолчанию - ASCII.

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

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

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

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

=========================================== Обновить, чтобы ответить Rob:

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

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'> строками, что, по-видимому, противоречит рекомендации немедленно преобразовать все в Юникод перед дальнейшей обработкой.

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

  • 0
    Так как utf-8 является кодировкой по умолчанию для 3.x, я не считаю этот хак некрасивым. Это поможет вам, если вам когда-нибудь придется портировать код на 3.x.
  • 0
    Я не верю, что "print fileid.encode ('ascii', 'ignore')" не будет работать.
Показать ещё 1 комментарий
Теги:
unicode

1 ответ

1
Лучший ответ

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

Как только строка будет успешно декодирована (в 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?, не уверен).

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

  • 0
    Спасибо, Роб - ему нужен был print fileid.encode('ascii', 'ignore') для работы, и я наконец- то print fileid.encode('ascii', 'ignore') что нужно кодировать / декодировать, благодаря твоему объяснению. Очень ценю ваше время.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню