MyTetra Share
Делитесь знаниями!
Кодировки в python
Время создания: 31.08.2017 21:02
Текстовые метки: knowledge
Раздел: Python
Запись: xintrea/mytetra_db_mcold/master/base/1501050626biku7hmlpa/text.html на raw.githubusercontent.com

Кодировки в python

2010-03-27 python кодировки

прочтение статьи занимает 4мин, с обдумыванием - 10мин :)
примечание: данная статья относится к python 2.x, но для python 3.x принцип тот же

Общее

В python есть 2 объекта работающими с текстом: unicode и str, объект unicode хранит символы в формате (кодировке) unicode, объект str является набором байт/символов в которых python хранит остальные кодировки (utf8, cp1251, cp866, koi8-r и др). Кодировку unicode можно считать рабочей кодировкой питона т.к. она предназначена для её использования в самом скрипте - для разных операций над строками. ВнВнешняя кодировка (объект str) предназначена для хранения и передачи текстовой информации вне скрипта, например для сохранения в файл или передачи по сети. Поэтому в данной статье я её назвал внешней. Самой используемой кодировкой в мире является utf8 и число приложений переходящих на эту кодировку растет каждый день, таким образом превращаясь в "стандарт". Эта кодировка хороша тем что для хранения текста она занимает оптимальное кол-во памяти и с помощью её можно закодировать почти все языки мира ( в отличие от cp1251 и подобных однобайтовых кодировок). Поэтому рекомендуется везде использовать utf8, и при написании скриптов.

Использование





Скрипт питона, в самом начале скрипта указываем кодировку файла и сохраняем в ней файл

# coding: utf8

либо

# -*- coding: utf-8 -*-




для того что-бы интерпретатор python понял в какой кодировке файл Строки в скрипте Строки в скрипте хранятся байтами, от кавычки до кавычки:

print 'Привет'

= 6 байт при cp1251 = 12 байт при utf8 Если перед строкой добавить символ u, то при запуске скрипта, эта байтовая строка будет декодирована в unicode из кодировки указанной в начале:

# coding:utf8

print u'Привет'


и если кодировка содержимого в файле отличается от указанной, то в строке могут быть "битые символы" Загрузка и сохранение файла


# 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:


a = <type 'str'> ╨в╨╡╨║╤Б╤В ╨▓ utf8

a2 = <type 'str'> Текст в utf8

b = <type 'unicode'> Текст в unicode


В последней строке 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


Результат


a = <type 'str'> Текст в utf8

b = <type 'unicode'> Текст в unicode

c = <type 'unicode'> Текст в 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'


Результат


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 питон не смог. Вывод списков

# 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']

3 Тест,списка

При выводе списка, происходит вызов [{repr}]() который возвращает внутреннее представление этого спиcка - print 1 и 2 являются аналогичными. Для корректного вывода списка, его нужно преобразовать в строку - print 3. Установка внешней кодировки при запуске

PYTHONIOENCODING=utf8 python 1.py

 
MyTetra Share v.0.59
Яндекс индекс цитирования