UnicodeEncodeError при присоединении к имени файла

Это выводит "UnicodeDecodeError: кодек 'ASCII' не может декодировать байт 0xc2 в положении 2: порядковый не в диапазоне (128)" при выполнении после кода:

filename = 'Spywaj.ttf'
print repr(filename)
>> 'Sp\xc2\x88ywaj.ttf'
filepath = os.path.join('/dirname', filename)

Но файл является правильным и существовал на диске. Имя файла было извлечено из, "разархивировали-l" команда. Как именам файлов соединения может понравиться это?

ОС и файловая система

Filesystem: ext3    relatime,errors=remount-ro 0       0
Locale: en_US.UTF-8

Предложение Alex os.path.join работает теперь, но я все еще не могу получить доступ к файлу на диске с именем файла, к которому это присоединилось.

filename = filename.decode('utf-8')
filepath = os.path.join('/dirname', filename)
print filepath
>> /dirname/u'Sp\xc2\x88ywaj.ttf'
print os.path.isfile(filepath)
>> False

new_filepath = filepath.encode('Latin-1').encode('utf-8')
print new_filepath
>> /dirname/u'Sp\xc2\x88ywaj.ttf'
print type(filepath)
>> <type 'unicode'>
print os.path.isfile(new_filepath)
>> False

valid_filepath = glob.glob('/dirname/*.ttf')[0]
print valid_filepath
>> /dirname/Spywaj.ttf (SO cannot display the chars in filename)
print type(valid_filepath)
>> <type 'str'>
print os.path.isfile(valid_filepath)
>> True
8
задан jack 5 January 2010 в 06:18
поделиться

3 ответа

Как в латинице-1 (ISO-8859-1), так и в Windows-1252, 0xc2 означало бы заглавную букву A с круговым акцентом... кажется, нигде в коде, который вы показываете! Не могли бы вы добавить a

print repr(filename)

перед вызовом os.path.join (а также поместить '/dirname' в переменную и распечатать ее переиздание для полноты?). Я думаю, что, возможно, этот шальной символ есть , но по какой-то причине вы его не видите -- repr откроет его.

Если у вас в имени файла есть латинский-1 (или Win-1252) не-Ascii символ, вы должны использовать Юникод -- и/или, в зависимости от вашей операционной системы и файловой системы, некоторую специфическую кодировку этого символа.

Edit: операционная система подтверждает, благодаря repr, что на самом деле существует два байта, которые не могут быть ASCII -- 0xc2, а затем 0x88, что соответствует тому, что операционная система думает, что это один нижний регистр L. Ну, эта последовательность была бы Unicode заглавной A с кареттой (кодовая точка 0x88) в справедливо популярной кодировке UTF-8 - как это может выглядеть как строчная L для объяснения нищих OP, но я представляю некоторые шрифты могут быть достаточно безумными с графической точки зрения, чтобы позволить себе такую путаницу.

Поэтому я сначала попробую filename = filename.decode('utf-8') -- это должно позволить os.path.join работать. Если open then balks at the result Unicode string (это может сработать, в зависимости от файловой системы и операционной системы), то следующая попытка - попробовать использовать объект Юникод .encode('Latin-1') и .encode('utf-8'). Если ни одна из кодировок не работает, то информация об используемой операционной системе и файловой системе, которую операционная система, я полагаю, еще не дала, становится критичной.

.
8
ответ дан 5 December 2019 в 10:41
поделиться

Проблема с доказательствами 1 ###

Выбрасывает "UnicodeDecodeError: Кодек 'ascii' не может декодировать байт 0xc2 в позиции 2: ordinal not in range(128)" при выполнении следующего кода:

filename = 'Spywaj.ttf'
print repr(filename)
>> 'Sp\xc2\x88ywaj.ttf'
filepath = os.path.join('/dirname', filename)

Я не понимаю, как можно получить это исключение -- оба аргумента os. path.join являются объектами str. Нет причин пытаться преобразовать что-либо в юникод. Вы уверены, что приведенный выше код - это именно то, что вы запустили?

Проблема с доказательствами 2

Предложение Алекса os.path.join сейчас работает, но я все еще не могу получить доступ к файлу на диске с именем файла, к которому он присоединился.

filename = filename.decode('utf-8')
filepath = os.path.join('/dirname', filename)
print filepath
>> /dirname/u'Sp\xc2\x88ywaj.ttf'

Извините, если предположить, что имя файла не изменилось по сравнению с предыдущим фрагментом, то это определенно невозможно. Похоже на результат os.path.join('/dirname', repr(filename)) ... пожалуйста, убедитесь, что вы опубликовали код, который вы на самом деле запустили, вместе с реальным выводом (и реальной трассировкой, если таковая имеется).

Confusion

new_filepath = filepath.encode('Latin-1').encode('utf-8')

Alex имел в виду попробовать дважды, каждый раз с одной из этих кодировок - а не один раз с обеими кодировками! Так как все символы в filepath были в диапазоне ASCII (см. проблему с доказательствами 2), эффект был просто filepath.encode('ascii')

Простое решение

Вы знаете, как найти имя файла, который вас интересует:

valid_filepath = glob.glob('/dirname/*.ttf')[0]

Если вам нужно жестко закодировать это имя в вашем скрипте, вы можете использовать функцию repr(), чтобы получить представление, которое вы можете ввести в ваш скрипт, не беспокоясь о utf8, unicode, кодировке, декодировании и всех этих шумах:

print repr(valid_filepath)

Предположим, что он печатает '/dirname/Sp\xc2\x88ywaj.ttf' ... тогда все, что вам нужно сделать, это аккуратно скопировать это и вставить его в свой сценарий:

file_path = '/dirname/Sp\xc2\x88ywaj.ttf'
0
ответ дан 5 December 2019 в 10:41
поделиться
[
filename = filename.decode('utf-8').encode("latin-1")
] [

] работает на меня с файлом из [] Splywaj.zip[][

]. [
>>> os.path.isfile(filename.decode("utf8").encode("latin-1"))
True
>>>
]
2
ответ дан 5 December 2019 в 10:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: