Кодировка 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 вопроса выше ответили.