Я использую mutagen для преобразования данных тегов ID3 из CP-1251/CP-1252 до UTF-8. В Linux проблем нет. Но в Windows при вызове SetValue() на wx.TextCtrl возникает ошибка:
UnicodeDecodeError: кодек ‘ascii’ не может декодировать байт 0xc3 в позиции 0: порядковый не в диапазоне (128)
Исходная строка (предположительно закодированная CP-1251), которую я вытягиваю из mutagen:
Я попытался преобразовать это в UTF-8:
. и даже изменение кодировки по умолчанию от ASCII до UTF-8:
. Но я получаю ту же ошибку.
Если вы точно знаете, что у вас есть cp1251 на вашем входе, вы можете сделать
Ваша строка d является строкой Unicode, а не строкой в кодировке UTF-8! Таким образом, вы не можете decode() его, вы должны encode() его использовать для UTF-8 или любого необходимого вам кодирования.
(это то, что вы делали бы в самом конце всей обработки, если вам нужно сохранить его как файл с кодировкой UTF-8, например).
Если ваш вход находится в другом кодировании, это наоборот:
Если d — правильная строка Юникода, то d.encode(‘utf-8’) дает кодированную UTF-8. Не проверяйте его путем печати, хотя может быть, что он просто не отображается должным образом из-за кодовых страниц. Шеняниганы.
Я бы предпочел добавить комментарий к Александру Степаненко, но моя репутация пока не позволяет. У меня была аналогичная проблема с конвертированием тэгов MP3 из CP-1251 в UTF-8, и решение для кодирования/декодирования/кодирования работало для меня. За исключением того, что мне пришлось заменить первую кодировку на "latin-1", которая по существу преобразует строку Unicode в байтовую последовательность без реальной кодировки:
и для сохранения обратно с использованием, например, мутагена, его не нужно кодировать:
Я потерял половину своего дня, чтобы найти правильный ответ. Так что если вы получили строку unicode из внешнего источника windows-1251, закодированного (с веб-сайта в моей ситуации), вы увидите в консоли Linux что-то вроде этого:
Это неправильная презентация ваших данных в формате unicode. Итак, Тим Пицкер прав. Вы должны сначала закодировать(), затем декодировать(), а затем снова закодировать, чтобы исправить кодировку.
Итак, в моем случае эта странная строка была сохранена в "текстовой" переменной, а строка:
"Своя 2-х комнатная квартира с отличным ремонтом. "
Да, это тоже сходит с ума. Но это работает!
P.S. Сохраняя файл, вы должны сделать то же самое.
В этом ответе я привел некоторую релевантную информацию о тексте кодирования/декодирования: тут
Чтобы добавить к этому здесь, важно подумать о тексте в одном из двух возможных состояний: "закодировано" и "декодировано"
‘decoded’ означает, что он находится во внутреннем представлении вашим интерпретатором/библиотеками, которые могут использоваться для манипулирования символами (например, поиск, преобразование регистров, нарезка подстроки, количество символов. ) или отображение (поиск кодовой точки в шрифте и рисовании глифа), но не может быть передан или запущен в процессе работы.
‘encoded’ означает, что это байтовый поток, который можно передавать, как и любые другие данные, но не полезен для манипуляции или отображения.
Если вы раньше работали с сериализованными объектами, рассмотрите "декодированный" как полезный объект в памяти и "закодированный" для сериализованной версии.
‘xc1xe5xebxe0xff xffxe1xebxfbxedxff xe3xf0xeexecxf3’ — ваша кодированная (или сериализованная) версия, предположительно закодированная cp1251. Эта кодировка должна быть правильной, потому что "язык" используется для сериализации символов и необходим для воссоздания символов в памяти.
В python есть 2 объекта работающими с текстом: unicode и str, объект unicode хранит символы в формате (кодировке) unicode, объект str является набором байт/символов в которых python хранит остальные кодировки (utf8, cp1251, cp866, koi8-r и др).
Кодировку unicode можно считать рабочей кодировкой питона т.к. она предназначена для её использования в самом скрипте — для разных операций над строками.
Внешняя кодировка (объект str) предназначена для хранения и передачи текстовой информации вне скрипта, например для сохранения в файл или передачи по сети. Поэтому в данной статье я её назвал внешней. Самой используемой кодировкой в мире является utf8 и число приложений переходящих на эту кодировку растет каждый день, таким образом превращаясь в "стандарт".
Эта кодировка хороша тем что для хранения текста она занимает оптимальное кол-во памяти и с помощью её можно закодировать почти все языки мира ( в отличие от cp1251 и подобных однобайтовых кодировок). Поэтому рекомендуется везде использовать utf8, и при написании скриптов.
Использование
Скрипт питона, в самом начале скрипта указываем кодировку файла и сохраняем в ней файл
для того что-бы интерпретатор python понял в какой кодировке файл
Строки в скрипте
Строки в скрипте хранятся байтами, от кавычки до кавычки:
= 6 байт при cp1251
= 12 байт при utf8
Если перед строкой добавить символ u, то при запуске скрипта, эта байтовая строка будет декодирована в unicode из кодировки указанной в начале :
и если кодировка содержимого в файле отличается от указанной, то в строке могут быть "битые символы"
Загрузка и сохранение файла
Текст в скрипте
Процедуре print текст желательно передавать в рабочей кодировке либо кодировать в кодировку ОС.
Результат скрипта при запуске из консоли windows XP:
a2 = Текст в utf8
b = Текст в unicode
В последней строке print преобразовал unicode в cp866 автоматический, см. следующий пункт
Авто-преобразование кодировки
В некоторых случаях для упрощения разработки python делает преобразование кодировки, пример с методом print можно посмотреть в предыдущем пункте.
В примере ниже, python сам переводит utf8 в unicode — приводит к одной кодировке для того что-бы сложить строки.
Результат
a = Текст в utf8
b = Текст в unicode
c = Текст в utf8Текст в unicode
Как видим результирующая строка "c" в unicode. Если бы кодировки строк совпадали то авто-перекодирования не произошло бы и результирующая строка содержала кодировку слагаемых строк.
Авто-перекодирование обычно срабатывает когда происходит взаимодействие разных кодировок.
Пример авто-преобразования кодировок в сравнении
Результат
1. utf8 and unicode true
2. utf8 and cp1251 false
script.py:10: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode — interpreting them as being unequal
print ‘3. cp1251 and unicode’, ‘true’ if u’Слово’.encode(‘cp1251′) == u’Слово’ else ‘false’
3. cp1251 and unicode false
В сравнении 1, кодировка utf8 преобразовалась в unicode и сравнение произошло корректно.
В сравнении 2, сравниваются кодировки одного вида — обе внешние, т.к. кодированы они в разных кодировках условие выдало что они не равны.
В сравнении 3, выпало предупреждение из за того что выполняется сравнение кодировок разного вида — рабочая и внешняя, а авто-декодирование не произошло т.к. стандартная внешняя кодировка = utf8, и декодировать строку в кодировке cp1251 методом utf8 питон не смог.
Вывод списков
Результат:
1 [‘xd0xa2xd0xb5xd1x81xd1x82’, ‘xd1x81xd0xbfxd0xb8xd1x81xd0xbaxd0xb0’]
2 [‘xd0xa2xd0xb5xd1x81xd1x82’, ‘xd1x81xd0xbfxd0xb8xd1x81xd0xbaxd0xb0’]
При выводе списка, происходит вызов [
Установка внешней кодировки при запуске
В обучении ребенка важно правильное толкование окружающего его мира. Существует масса полезных журналов которые начнут экологическое воспитание дошкольников правильным путем. Развивать интерес к окружающему миру очень трудный но интересный процесс, уделите этому особое внимание.
I’m trying to convert file content from Windows-1251 (Cyrillic) to Unicode with Python. I found this function, but it doesn’t work.
How can I do that?
3 Answers 3
Is this what you intend to do?
This is just a guess, since you didn’t specify what you mean by "doesn’t work".
If the file is being generated properly but appears to contain garbage characters, likely the application you’re viewing it with does not recognize that it contains UTF-8. You need to add a BOM to the beginning of the file — the 3 bytes 0xEF,0xBB,0xBF (unencoded).
If you use the codecs module to open the file, it will do the conversion to Unicode for you when you read from the file. E.g.:
This only makes sense if you’re working with the file’s data in Python. If you’re trying to convert a file from one encoding to another on the filesystem (which is what the script you posted tries to do), you’ll have to specify an actual encoding, since you can’t write a file in "Unicode".