Как стать автором
Обновить

Комментарии 53

Годная, полезная статья.
Я бы еще раскрыл тему как читать/писать юникодные файлы: codecs.open вместо file() и про PEP 0263.
по поводу файлов

#! /usr/bin/env python
# -*- coding: utf-8 -*-

операции с файлами становятся уникодными=)

ну еще со строками магия проходит вроде
регулярки работают
m=re.match('^(第)([0-9]+)(届|期)',s)

Как практика показывает, входные данные лучше отгонять в UTF-8
тогда проблемы вроде того что одни и теже данные python, c++ и так далее не сильно актуальные…
Отдельно надо выделить если происходят операции за Базой данных тут кодировки тоже важно…

З.Ы каждый программист должен начинать новый язык с UTF-8 / Unicode :) решать вопрос чтобы устойчивая программа была к любым символам
Не операции становятся уникодными, а исходный текст скрипта :).
Файлы [данных] все же придется читать и декодировать руками.

> входные данные лучше отгонять в UTF-8

Ни в коем случае! UTF-8 — это внешнее представление. Входные данные надо отгонять в юникод, со всеми строками работать только в юникоде, а сохранять снова в UTF-8. Кстати, в C++ c UTF-8 вообще можно повеситься (ну или забыть работу со строками).
Насчет входных файлов соглашусь…

У меня просто все данные в UTF-8, входные из файлов поэтому работает 2.6/2.7
Внешение представление в UTF-8 спасает…

UTF-8 для символов a-z 1byte если идет кирилица А_Я и так далее 2 byte.

С точки зрения C/C++ когда strlen(ansi) = 10 с точки зрения strlen(utf-8) 10 длина не понятна(может символы 1 +2 +2 +2 +1+1 ).

Если код не ориентирован на чёткий поиск, а склейка строк то strcpy/strcat можно пользовать…

з.ы. пора тему Unicode / UTF-8/ UTF-16 как курс или пособие, обобщение для разных языков…
Чё за бред? Хабр — УГ.
Толсто.
Терпите. Скоро вас запикает НЛО.
Что полезного сделали вы для хабрсообщества, чтоб его критиковать?
Хабрасэппуку?
Это вы зря. Мне недавно пришла идея автоматического пополнения словаря с использованием нейронной сети. Идея не нова, просто самообучался. Столкнулся с проблемой кодировки, перерыл полинтернета. Нашел ответы на вопросы, но все очень разрозненно, плюс умные люди помогли, теория все равно осталась мне не понятна. А это фактически единственная статья в рунете, которая все раскладывает по полочкам.
Не знаю, столкнулся с юникодом в джанге, нашел решение за 5 минут. А в статье дикая мешанина из того, что такое юникод и работа с кодировками отличными от ascii в питоне.
ru.wikipedia.org/wiki/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4

кстати, по работе с кодировками по ссылке есть все в одном месте (например в self.статье про ignore, replace всего одна строчка, а в доках масса примеров и даже BOM упомянут :)):
docs.python.org/howto/unicode.html
Непонятно, чем «символы» отличаются от байтов. В конечном счете они все равно хранятся как любая другая информация в памяти — как байты. Поясните разницу.
Символ — это, например, «CYRILLIC SMALL LETTER A», а байт — это нолики и еденицы, например '\xe0'. Для того, что б байт стал символом, необходима кодировка. И в зависимоти от кодировки, этот байт (или байты) может представлять разные символы.
Определение одного символа не обязательно умещается в один байт.
Я и сказал «чем символы отличаются от байтов?» а не «чем символ отличается от байта?».
Я понимаю, что символ может быть больше байта, я не понимаю вот это «не обязательно».
То есть в юникоде разные символы имеют разный размер? Вообще что можно почитать по этому поводу. поменьше и попроще, чем стандарт?
В Unicode определяются code points. Но code point — это число + название, он не задаёт байты. Для того, чтобы преобразовать последовательность code points в байты, вам нужно выбрать некоторый Unicode Transfotmation Format (UTF) и закодировать в соответствии с его правилами.
Да, но число — разве оно и не есть эти самые байты? А названия — разве не однозначно соответствуют числам?
Нет, число — это просто целое число. Оно может быть закодировано в виде байт (причём правила различны в зависимости от UTF, и ещё и не всеми битами этих байтов).
Один символ может занимать несколько байт.
Похоже что косяки машинного перевода немного накладывает отпечаток…
...«Хорошо, я понял чем есть строка.»…

А так по логике вещей показалось странным, что:
байты в Unicode — это кодирование
а Unicode в батый — это де-кодирование

интуитивно хочется наоборот… хотя смысл, понятен, и зависит от того что-во-что кодировать и следовательно де-кодировать
А мне именно такая логика кажется естественной.
У символа есть «код», мы получаем код из символа декодированием оного.
Нет, это просто стиль такой выбран. А вобще автор совсем не русско-говорящий :)

>> интуитивно хочется наоборот

дык на самом деле и есть наоборот — байты в Unicode — это декодирование.
"string".decode('ascii') # декодируем в  юникод
u"string".encode('ascii') # переводим юникод в кодировку ascii


Все как раз наоборот
>>
На данный момент в Юникод-стандарте есть немного более 100 тысяч символов, тогда как UTF-16 позволяет поддерживать более одного миллиона (UTF-8 — и того больше).


На сколько я понимаю, UTF-16 может кодировать максимум 65 535 символов. Возможно, вы ошиблись?
Тогда UTF-8 кодирует 255 символов?

Нет. «16» в UTF-16 означает размер используемого слова: каждый code point в UTF-16 кодируется одним или более 16-битными словами.
Да, вы правы. Принцип работы UTF-16 аналогичен UTF-8 с разницей лишь в размере слова.

До этого момента я свято верил в то, что wchar_t в Windows — это UTF-16. Оказывается, это UCS-2 — строго 16-битная кодировка без возможности расширения до 32 бит.
16 в названии совсем не значит, что используются 16 бит\2 байта\65 535 доступных комбинаций. Деталей кодировки не знаю, число взял сами знаете откуда. Посмотреть детали думаю можно там же (пока не закрыли в знак протеста против SOPA:) )
Согласно Вики и в UTF-8 и в UTF-16 равное число возможных символов — 1,112,064
Совершенно верно. Но можно расширить по аналогии правила построения UTF-8 на более длинные последовательности и получить так называемые overlong sequences. Хотя в стандарте прямо написано, что они ошибочны, к сожалению некоторые «хакеры» считают, что они выше стандарта и говорят, что в UTF-8 больше кодов, чем написано в стандарте, да ещё и реализуют их поддержку в своих программах (например, в eglibc bugs.debian.org/cgi-bin/bugreport.cgi?bug=555922 ).

И да, не называйте юникодные code points символами. Не каждый code point можно нарисовать в виде символа и даже есть такие code points, которые называются noncharacters. См. также en.wikipedia.org/wiki/Mapping_of_Unicode_characters
ммм… Code point. Пасиб, проще с такой терминологией работать.
Какой-то русский аналог у этого названия есть?
Не слышал, но возможно «кодовая позиция Unicode»?
прочитал ссылку на баг в eglibc. мдааа…
Ещё один кейс на проверку в программах (я тестировщик). Правда не очень понятно кого винить потом проблеме — своих разработчиков, или разработчиков билиотеки которую они использовали.
Особенно «порадовал» комментарий — «Nobody has ever shown any evidence why this is a bad idea.»
Стандарты видимо люди тоже просто так придумывали…
> в тоже время в кодировке ISO-8859-1 это греческая "ß".
В ISO-8859-1 нет греческих букв. Это немецкая Eszett. (на правах занудства)
Спасибо за занудство:)
Хорошая статья, советую еще раскрыть тему локалей, без этого материал неполный.

Жаль что не смотря на теорию проблема кодировок это сверхбольное место питона, которое каждый раз съедает у меня массу сил и времени. Заткнулся какой ни будь встроенный модуль для работы с gzip на русскоязычных именах файлах и рабочий день коту под хвост.

В python 3000 демонстрировать особо нечего, для самого питона проблема решена на корню как в java, все строки — юникод, на практике ад с портированием библиотек и, имхо, эта ветка сдохнет и на ее место доэволюционирует 2.x, х/з как при этом решится проблема со строками.
Помер как раз 2.х
3.3 выкатят к осени.
Трудности с портированием есть, но «адом» я их не назову.
Честно говоря, до этой статьи я понимал что такое кодировки и как с ними работать.
Очень тяжелая статья для новичков, которая лишь внесет кашу в головы.
Увидел сначала сколько букв — испугался.
Когда осилил, понял, что не так уж и много. Читается нормально.
Полезная статья!
В вводной забыли про EBCDIC, они с ASCII практически ровесники.
Нужная статья, основная полезность направление decode / encode.
Некоторая мнемоника:
1. Для себя сделал ассоциации типа decode более тяжелое по звучанию соответственно создает тяжелый utf,
encode легкое создает легковесный байт.
2. Байты это непонятный код, который чтобы увидеть надо декодировать в символы (utf), а чтобы символы превратить в код (т.е. байты), их соответственно нужно закодировать (encode).
На виндах у петона вечные проблемы с юникодом, что у третьего, что у второго. На линуксе с этим проще.
Да и не только с юникодом.
Да, я по это причине все пытаюсь переползти на макось но пока не складывается.
А чем проблемность юникода в Windows вызвана?
видимо тем, что родная для винды CP1251
не волнуйтесь, в линуксе тоже есть вечные проблемы с вводом/выводом изнутри библиотек.
например, stderr направленный в файл — работает, а на консоль — падает, а на appengine — генерит servererror.
Правильно ли я понимаю, что если везде и всюду в константах и на входе программы будет только юникод (вместо байтстрок) — это избавит от проблем вида «UnicodeDecodeError» в крайне неожиданных местах?
(например, от лютых кабздецов, когда appengine-приложение падает в «server error» из-за того, что логгер не может нарисовать лог.)
А в каком формате сам python внутри хранит строки в 2.х и 3.х?
Строки (str)? Естественно, байты char[]
Unicode — платформозависимо, обычно UCS-2(4)
Хотя что понимать под «хранит внутри» — я о памяти запущенной программы.
Забавно, вот что по ссылке на перевод статьи Спольски :)
Меня спасает
# -*- coding: utf-8 -*-
from __future__ import unicode_literals


Таким образом весь текст становится unicode, если не укажете что он b'текст'
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории