Простой Python. Современный стиль программирования (Любанович) - страница 103

>b'☃'

Декодирование

Мы декодируем байтовые строки в строки Unicode. Когда мы получаем текст из какого-то внешнего источника (файлы, базы данных, сайты, сетевые API и т. д.), он закодирован в виде байтовой строки. Идея заключается в том, чтобы знать, какая кодировка была использована, чтобы мы могли ее декодировать и получить строку Unicode.

Проблема в следующем: никакая часть байтовой строки не говорит нам о том, какая была использована кодировка. Я уже упоминал опасности копирования/вставки с сайтов. Вы, возможно, посещали сайты, содержащие странные символы в том месте, где должны быть простые символы ASCII.

Создадим строку Unicode, которая называется place и имеет значение 'café':

>>>> place = 'caf\u00e9'

>>>> place

>'café'

>>>> type(place)

>

Закодируем ее в формат UTF-8 с помощью переменной bytes, которая называется place_bytes:

>>>> place_bytes = place.encode('utf-8')

>>>> place_bytes

>b'caf\xc3\xa9'

>>>> type(place_bytes)

>

Обратите внимание на то, что переменная place_bytes содержит пять байтов. Первые три похожи на ASCII (преимущество UTF-8), а последние два кодируют символ «é». Теперь декодируем эту байтовую строку обратно в строку Unicode:

>>>> place2 = place_bytes.decode('utf-8')

>>>> place2

>'café'

Это сработало, поскольку мы закодировали и декодировали строку с помощью кодировки UTF-8. Что, если бы мы указали декодировать ее с помощью какой-нибудь другой кодировки?

>>>> place3 = place_bytes.decode('ascii')

>Traceback (most recent call last):

>··File "", line 1, in

>UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 3:

>ordinal not in range(128)

Декодер ASCII сгенерировал исключение, поскольку байтовое значение 0xc3 некорректно в ASCII. Существуют и другие восьмибитные кодировки, где значения между 128 (80 в шестнадцатеричной системе) и 255 (FF в шестнадцатеричной системе) корректны, но не совпадают со значениями UTF-8:

>>>> place4 = place_bytes.decode('latin-1')

>>>> place4

>'café'

>>>> place5 = place_bytes.decode('windows-1252')

>>>> place5

>'café'

Ох.

Мораль этой истории — используйте кодировку UTF-8 всюду, где это возможно. Она работает, она поддерживается везде, вы можете с ее помощью выразить любой символ Unicode и быстро закодировать и декодировать.

Подробная информация

Если вы хотите узнать больше, вам могут помочь следующие ссылки:

• Unicode HOWTO (http://bit.ly/unicode-howto);

• Pragmatic Unicode (http://bit.ly/pragmatic-uni);

• The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) (