Юникод в Python 2.x — что это и зачем?

В реальном мире строковыми данными обмениваются в какой-то кодировке. Например, koi8-r, cp1251, utf-8. И когда тебе приходят данные, ты во многих случаях знаешь, какая это кодировка. Но когда тебе приезжают данные из разных мест в разных кодировках, работать с ними одновременно довольно напряжно — надо всегда об этом помнить.

Чтоб облегчить жизнь, внутри программ используют юникодные данные — это которые u'test'. Их можно получить декодированием обычной строки, типа 'test'.decode('utf-8'), и точно так же кодированием превратить в обычную строку: u'test'.encode('utf-8').

Юникод — это способ представления, а не хранения данных. Т.е. юникод — это стандарт, который сопоставляет символу какое-то число — те самые \u<номер>. А кодировка — это способ хранения этого числа, например UTF-81 хранит числа таким образом, что символы латиницы (символы с номером меньше 128) кодируются в один байт, и таким образом соответствует ASCII. При этом у кириллицы — двухбайтные символы.

Работа происходит так: ты получаешь какие-то данные от своего окружения, декодируешь их в юникод, работаешь, а когда отдаëшь наружу, опять превращаешь в строку. Наружу — это не только вывод на экран, это и запись в файлы, и в базу данных. Хотя драйверы БД (а тем более ORM) обычно сами преобразуют юникод в нужную кодировку.

Цель этой заметки — всего лишь дать базовое понятие о том, почему в питоне есть отдельный тип для юникодных данных, а для более полного понимания можно почитать разное:


  1. Unicode Transformation Format 

Comments: 11 (already: 5) Comment post

Слабовато. Новички это узнают в первый же день изучения Python. Стоило бы еще упомянуть, что в Python 3.x уже нет обычных строк, а вемь текст юникодный.

xstream , 14:34

Новички это узнают в первый же день изучения Python.

Если б они это узнавали, никто б таких вопросов, как задают, не задавал бы.

Alexander Solovyov , 14:38

Это после понимания кажется, что всё прозрачно и понятно, а до народ оооочень часто ругается на маловменяемые UnicodeEncodeError/ UnicodeDecodeError в дебрях чужого кода, часто путают encode/decode (усуглубляется тем, что оба метода есть и у str и у unicode), удивляются, почему print unicode_data это плохо, etc… Так что вводный пост, на который можно ссылаться в дальнейшем — это очень хорошо.

Я вот часто ссылаюсь на http://www.rupy.ru/member/5/#paper-6 $)

P.S.Хотя да, несколько запоздало, пора уже писать “Юникод в Py 3.1” :)

Юревич Юрий , 15:50

Кому пора, а кому и 2.х еще вполне актуален. ;)

Alexander Solovyov , 15:56

Кстати, я смотрел юникод в Py 3.0 пока в отпуске был. Много вопросов к нему. Особенно что касается неявных перекодировок данных “из внешнего мира” (os.environ, os.path). Надо будет Py 3.1 по этому поводу пощупать…

Юревич Юрий , 15:59

А ещё бывает такая стиуация когда кодируется в неправильную кодировку, потом перекодируется ещё в какую нибудь и вообще я даже ситуацию не могу толком описать, не то что методы решения.. В общем это я про русские мп3 тэги как вы наверное догадались..

hrundelok , 16:49

просто в ID3v1 используются однобайтовые строки, а многие проигрыватели музыки до сих пор позволяют писать данные в ID3v1. Вот в ID3v2 уже есть понятие кодировка, и многие проигрыватели им даже умеют как-то пользоваться.

Yuri Baburov , 18:15 (after 6 days)

Скажи вот у меня такой случай:

In [14]: resp.content
Out[14]: ‘\r\n\r\n\r\n\r\n\r\n<html xmlns=”http://www.w3.org/1999/xhtml”>\r\n <head>\r\n <meta http-equiv=”content-type” content=”text/html; charset=utf-8” />\r\n \r\n \n<title>Japanese innovation | \xd0\xaf\xd0\xbf\xd0\xbe\xd0\xbd\xd0\xb8\xd1\x8f \xd0\xb8\xd0\xbd\xd0\xbd\xd0\xbe\xd0\xb2\xd0\xb0\xd1\x86\xd0\xb8\xd0\xb8</title>\n\r\n

Что это за формат, и как его можно преворатить во что то читаемое (ну или такое где можно найти строку текста)

Oleg Tarasenko , 06:57 (after 50 days)

Самый обычный utf-8.

Alexander Solovyov , 18:41 (after 50 days)

resp.content.decode(‘utf-8’) если нужно найти строчку текста в title, можешь взять скажем beautifulsoup, elementtree или html5lib, или просто написать regexp. для этого перекодировать вообще не надо ничего — все сами разберутся с кодировкой (впрочем, не уверен насчёт elementtree, ну и regexp ничего не раскодирует, ессно).

Yuri Baburov , 01:07 (after 51 day)

В том то и дело что когда мне нужно вытянуть например значение alt атрибута в каком нибудь из img, то например запрос

    c = Client()                                                                                                                        
    response = BeautifulSoup(c.get("/").content)                                                                                        
    images = response.findAll('img')
    images[0]['alt'] дает эту же абракадабру (ой прости Саня utf-8)

хотя если написать: print response то текст (весь код страницы) будет читабельным. Как то можно с этим справиться?

Oleg Tarasenko , 07:08 (after 51 day)

Comment form for «Юникод в Python 2.x - что это и зачем?»

Required. 30 chars of fewer.

Required.

Comment post