Кодировка Python 2.7 "latin-1" используется вместо "UTF-8"

Мне известно, что существует множество дискуссий по проблеме кодирования "UTF-8" на Python 2, но я пока не смог найти решение своей проблемы. В настоящее время я создаю сценарий для получения имени файла и создания гиперссылки на него в xlwt, чтобы к нему можно было получить доступ с помощью щелчков в электронной таблице. Проблема в том, что некоторые из имен этих файлов включают не-ASCII символы.

Вопрос 1

Я использовал следующую строку, чтобы получить имя файла. Кстати, в папке только один файл.

>>f = filter(os.path.isfile, os.listdir(tmp_path))[0]

А потом

>>print f
'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc'
>>print sys.stdout.encoding
'UTF-8'
>>f.decode("UTF-8")
*** UnicodeDecodeError: 'utf8' codec can't decode byte 0xe7 in position 76: invalid continuation byte

Просматривая обсуждения здесь, я понял, что "\xe7\xe3o" не является кодировкой "UTF-8". Запуск следующей строки, кажется, подтверждает эту точку зрения.

>>f.decode("latin-1")
u'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc'

Мой вопрос тогда, почему переменная f кодируется в "latin-1", когда системное кодирование установлено в "UTF-8"?

вопрос 2

Хотя f.decode("latin-1") дает мне вывод, который я хочу, я все еще не могу предоставить переменную для функции гиперссылки в электронной таблице.

 >>data.append(["File", xlwt.Formula('HYPERLINK("%s";"%s")' % (os.path.join(dl_path,f.decode("latin-1")),f.decode("latin-1")))])
*** FormulaParseException: can't parse formula HYPERLINK("u'H:\\Mad Lab\\SE Doc Crawler\\bovespa\\download\\521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc's;"u'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc's)

По-видимому, закрывающая двойная кавычка была съедена и была заменена суффиксом "s". Может кто-нибудь помочь объяснить, что здесь происходит? 0.0

О, и если кто-то может предложить решение для вопроса 2 выше, то я буду очень благодарен - вы бы спасли мои выходные от страданий!

Заранее всем спасибо!

2 ответа

Решение

Добро пожаловать в запутанный мир кодирования! По крайней мере, есть кодировка файла, кодировка терминала и кодировка имени файла, и все три могут отличаться.

В Python 2.x цель состоит в том, чтобы получить строку Unicode (отличается от str) от закодированной ул. Проблема в том, что вы не всегда знаете кодировку, используемую для str так что это трудно расшифровать.

Когда используешь listdir() чтобы получить имена файлов, есть документированная, но часто пропускаемая причуда - если вы передадите str в listdir() вы закодированы str назад. Они будут закодированы в соответствии с вашей локалью. В Windows это будет 8-битный набор символов, например windows-1252,

Или пройти listdir() Строка Unicode вместо.

Например

os.listdir(u'C:\\mydir')

Обратите внимание u префикс

Это вернет правильно декодированные имена файлов Unicode. В Windows и OS X это довольно надежно, если язык вашей среды не был испорчен.

В твоем случае, listdir() вернется:

u'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc'

Опять же, обратите внимание на u префикс. Теперь вы можете распечатать это на своей консоли PyCharm без изменений.

Например

f = filter(os.path.isfile, os.listdir(tmp_path))[0]
print f

Что касается Вопроса 2, я не стал исследовать дальше, а просто напечатал вывод в виде строк Unicode, а не объектов xlwt, из-за нехватки времени. Я могу продолжить проект, хотя и не понимаю, что здесь пошло не так. В этом смысле на 2 вопроса выше ответили.

Другие вопросы по тегам