- Ошибки при конвертации#
- Обработка ошибок#
- Параметр errors в encode#
- Параметр errors в decode#
- Python encoding problem utf8
- Проблемы с кодировкой в Python
- Использование
- Строки в скрипте
- Загрузка и сохранение файла
- Текст в скрипте
- Авто-преобразование кодировки
- Результат
- Пример авто-преобразования кодировок в сравнении
- Результат
- Вывод списков
- Результат:
- Установка внешней кодировки при запуске
Ошибки при конвертации#
При конвертации между строками и байтами очень важно точно знать, какая кодировка используется, а также знать о возможностях разных кодировок.
Например, кодировка ASCII не может преобразовать в байты кириллицу:
In [32]: hi_unicode = 'привет' In [33]: hi_unicode.encode('ascii') --------------------------------------------------------------------------- UnicodeEncodeError Traceback (most recent call last) ipython-input-33-ec69c9fd2dae> in module>() ----> 1 hi_unicode.encode('ascii') UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
Аналогично, если строка «привет» преобразована в байты, и попробовать преобразовать ее в строку с помощью ascii, тоже получим ошибку:
In [34]: hi_unicode = 'привет' In [35]: hi_bytes = hi_unicode.encode('utf-8') In [36]: hi_bytes.decode('ascii') --------------------------------------------------------------------------- UnicodeDecodeError Traceback (most recent call last) ipython-input-36-aa0ada5e44e9> in module>() ----> 1 hi_bytes.decode('ascii') UnicodeDecodeError: 'ascii' codec can't decode byte 0xd0 in position 0: ordinal not in range(128)
Еще один вариант ошибки, когда используются разные кодировки для преобразований:
In [37]: de_hi_unicode = 'grüezi' In [38]: utf_16 = de_hi_unicode.encode('utf-16') In [39]: utf_16.decode('utf-8') --------------------------------------------------------------------------- UnicodeDecodeError Traceback (most recent call last) ipython-input-39-4b4c731e69e4> in module>() ----> 1 utf_16.decode('utf-8') UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
Наличие ошибок — это хорошо. Они явно говорят, в чем проблема. Хуже, когда получается так:
In [40]: hi_unicode = 'привет' In [41]: hi_bytes = hi_unicode.encode('utf-8') In [42]: hi_bytes Out[42]: b'\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82' In [43]: hi_bytes.decode('utf-16') Out[43]: '뿐胑룐닐뗐苑'
Обработка ошибок#
У методов encode и decode есть режимы обработки ошибок, которые указывают, как реагировать на ошибку преобразования.
Параметр errors в encode#
По умолчанию encode использует режим strict — при возникновении ошибок кодировки генерируется исключение UnicodeError. Примеры такого поведения были выше.
Вместо этого режима можно использовать replace, чтобы заменить символ знаком вопроса:
In [44]: de_hi_unicode = 'grüezi' In [45]: de_hi_unicode.encode('ascii', 'replace') Out[45]: b'gr?ezi'
Или namereplace, чтобы заменить символ именем:
In [46]: de_hi_unicode = 'grüezi' In [47]: de_hi_unicode.encode('ascii', 'namereplace') Out[47]: b'gr\\Nezi'
Кроме того, можно полностью игнорировать символы, которые нельзя закодировать:
In [48]: de_hi_unicode = 'grüezi' In [49]: de_hi_unicode.encode('ascii', 'ignore') Out[49]: b'grezi'
Параметр errors в decode#
В методе decode по умолчанию тоже используется режим strict и генерируется исключение UnicodeDecodeError.
Если изменить режим на ignore, как и в encode, символы будут просто игнорироваться:
In [50]: de_hi_unicode = 'grüezi' In [51]: de_hi_utf8 = de_hi_unicode.encode('utf-8') In [52]: de_hi_utf8 Out[52]: b'gr\xc3\xbcezi' In [53]: de_hi_utf8.decode('ascii', 'ignore') Out[53]: 'grezi'
Режим replace заменит символы:
In [54]: de_hi_unicode = 'grüezi' In [55]: de_hi_utf8 = de_hi_unicode.encode('utf-8') In [56]: de_hi_utf8.decode('ascii', 'replace') Out[56]: 'gr��ezi'
Python encoding problem utf8
Быстрое, но не всегда работающее решение
Вначале скрипта надо прописать:
Соответственно, сам текст скрипта должен быть в кодировке UTF-8.
Но не все так просто. В Python 2.7.x, даже если прописать эту строку в начало файла с исходником, даже если все файлы с исходниками будут в кодировке UTF-8, то не исключена ситуация, что всеравно появится ошибка:
UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xd0 in position 0: ordinal not in range(128)
В куче статей, которыми наполнен интернет, почему-то предлагаются частные решения этой глобальной проблемы. Предлагают использовать запись строк с буквой u в начале: u»Это строка» . Другой предлагаемый метод — е сли у вас встречаются строки на русском языке или с кириллическими символами, перекодируйте их в юникод с помощью встроенного в строку метода decode() :
Но такой метод решения проблем — это все равно что вилкой копать скалу. Исковыряете весь код лишними строками, а проблема как была так и останется.
Однако решение все-таки есть
В начале модуля, в котором возникает ошибка, надо прописать:
# Устранение проблем с кодировкой UTF-8
И ошибка кодировки исчезнет.
- Использование UTF-8 в Python, устранение проблем с кодировкой
- Основные конструкции языка Python
- Пример стиля форматирования в Python
- Оператор pass
- Цикл с постусловием в Python
- Как выйти из Python программы с кодом завершения
- Python: пример открытия файла и перебора строк в нём
- Python: работа со строками
- Python: работа со списками
- Python: тип данных bool и операторы сравнения
- Python: запуск внешних программ и команд
- Python: запуск внешней программы или команды
- Работа с директориями и файлами в Python
- Регулярные выражения в Python, простой пример
- Python: выход из программы с кодом возврата
- Python: преобразования типов, определение типа переменной
- Python: списки, кортежи, словари
- Аналог PHP-функции trim() в Python
- Глобальные переменные в языке Python
- Руководство по магическим методам в Питоне
- Как в Python подсчитать количество страниц в PDF-файле
- Основы языка программирования Python за 10 минут
- Импорт скриптов (библиотек) в Python
- Функции с неизвестным числом аргументов в Python и параметры по умолчанию
- Классы в Python для PHP-разработчиков
- Сериализация объектов в Python
- Как в Python получить UNIX Timestamp
- Особенности импорта модулей в Python
- О порядке поиска пакетов и модулей для импорта в Python
- Сводная таблица методов для базовых типов Python2 и Python3
- Наследование в Python — краткое пояснение
- Как в Python вызвать метод того же класса
- Курс «Программирование на Python» от преподавателей СПбАУ РАН и ИТМО
- Бесплатный курс pythontutor.ru (Питонтьютор)
- Краткое описание библиотеки math
- Как установить пакет PIP на компьютере без сети Интернет
- Лямбда-функции в языке Python. Использование map/filter/reduce. Простое объяснение
- Как настроить запуск главного скрипта в Python-проекте в VSCode
- Как в VSCode в проекте на Python обеспечить навигацию по коду
- Как в Python вызвать метод объекта по имени, которое написано в виде строковой переменной?
- 10 ловушек в Python
- 10 хитростей Python, о которых полезно знать
- Django: основы работы
Проблемы с кодировкой в Python
10 февраля 2013 г. Archy Просмотров: 50782 RSS 4
Запуск программ на Python » Python и запуск програм python unicode, python utf-8, python windows-1251, python кодировка
В python есть 2 объекта работающими с текстом: unicode и str, объект unicode хранит символы в формате (кодировке) unicode, объект str является набором байт/символов в которых python хранит остальные кодировки (utf8, cp1251, cp866, koi8-r и др).
Кодировку unicode можно считать рабочей кодировкой питона т.к. она предназначена для её использования в самом скрипте — для разных операций над строками.
Внешняя кодировка (объект str) предназначена для хранения и передачи текстовой информации вне скрипта, например для сохранения в файл или передачи по сети. Поэтому в данной статье я её назвал внешней. Самой используемой кодировкой в мире является utf8 и число приложений переходящих на эту кодировку растет каждый день, таким образом превращаясь в «стандарт».
Эта кодировка хороша тем что для хранения текста она занимает оптимальное кол-во памяти и с помощью её можно закодировать почти все языки мира ( в отличие от cp1251 и подобных однобайтовых кодировок). Поэтому рекомендуется везде использовать utf8, и при написании скриптов.
Использование
Скрипт питона, в самом начале скрипта указываем кодировку файла и сохраняем в ней файл
для того что-бы интерпретатор python понял в какой кодировке файл
Строки в скрипте
Строки в скрипте хранятся байтами, от кавычки до кавычки:
Если перед строкой добавить символ u, то при запуске скрипта, эта байтовая строка будет декодирована в unicode из кодировки указанной в начале :
и если кодировка содержимого в файле отличается от указанной, то в строке могут быть «битые символы»
Загрузка и сохранение файла
# coding: utf8 # Загружаем файл с кодировкай utf8 text = open('file.txt','r').read() # Декодируем из utf8 в unicode - из внешней в рабочую text = text.decode('utf8') # Работаем с текстом text += text # Кодируем тест из unicode в utf8 - из рабочей во внешнюю text = text.encode('utf8') # Сохраняем в файл с кодировкий utf8 open('file.txt','w').write(text)
Текст в скрипте
# coding: utf8 a = 'Текст в utf8' b = u'Текст в unicode' # Эквивалентно: b = 'Текст в unicode'.decode('utf8') # т.к. сам скрипт хранится в utf8 print 'a =',type(a),a # декодируем из utf-8 в unicode и далее unicode в cp866 (кодировка консоли winXP ru) print 'a2 =',type(a),a.decode('utf8').encode('cp866') print 'b =',type(b),b
Процедуре print текст желательно передавать в рабочей кодировке либо кодировать в кодировку ОС.
Результат скрипта при запуске из консоли windows XP:
В последней строке print преобразовал unicode в cp866 автоматический, см. следующий пункт
Авто-преобразование кодировки
В некоторых случаях для упрощения разработки python делает преобразование кодировки, пример с методом print можно посмотреть в предыдущем пункте.
В примере ниже, python сам переводит utf8 в unicode — приводит к одной кодировке для того что-бы сложить строки.
# coding: utf8 # Устанавливаем стандартную внешнюю кодировку = utf8 import sys reload(sys) sys.setdefaultencoding('utf8') a = 'Текст в utf8' b = u'Текст в unicode' c = a + b print 'a =',type(a),a print 'b =',type(b),b print 'c =',type(c),c
Результат
c = Текст в utf8Текст в unicode
Как видим результирующая строка «c» в unicode. Если бы кодировки строк совпадали то авто-перекодирования не произошло бы и результирующая строка содержала кодировку слагаемых строк.
Авто-перекодирование обычно срабатывает когда происходит взаимодействие разных кодировок.
Пример авто-преобразования кодировок в сравнении
# coding: utf8 # Устанавливаем стандартную внешнюю кодировку = utf8 import sys reload(sys) sys.setdefaultencoding('utf8') print '1. utf8 and unicode', 'true' if u'Слово'.encode('utf8') == u'Слово' else 'false' print '2. utf8 and cp1251', 'true' if u'Слово'.encode('utf8') == u'Слово'.encode('cp1251') else 'false' print '3. cp1251 and unicode', 'true' if u'Слово'.encode('cp1251') == u'Слово' else '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 питон не смог.
Вывод списков
# coding: utf8 d = ['Тест','списка'] print '1',d print '2',d.__repr__() print '3',','.join(d)
Результат:
1 [‘\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82’, ‘\xd1\x81\xd0\xbf\xd0\xb8\xd1\x81\xd0\xba\xd0\xb0’]
2 [‘\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82’, ‘\xd1\x81\xd0\xbf\xd0\xb8\xd1\x81\xd0\xba\xd0\xb0’]
При выводе списка, происходит вызов []() который возвращает внутреннее представление этого спиcка — print 1 и 2 являются аналогичными. Для корректного вывода списка, его нужно преобразовать в строку — print 3.
Установка внешней кодировки при запуске
PYTHONIOENCODING=utf8 python 1.py
В обучении ребенка важно правильное толкование окружающего его мира. Существует масса полезных журналов которые начнут экологическое воспитание дошкольников правильным путем. Развивать интерес к окружающему миру очень трудный но интересный процесс, уделите этому особое внимание.