Рубрики
Без рубрики

Руководство для начинающих для Unicode в Python

Автор оригинала: FreeCodeCapm Team.

Джимми Чжан

Однажды я провел пару разочаровывающих дней на работе, изучающую, как правильно справляться с строками Unicode в Python. В течение этих двух дней я съел много закусок – примерно одна сумка из золотой рыбки на одну из этих ошибок возникла, что должно быть слишком известно тем, кто программирует с Python:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xf0 in position 0: ordinal not in range(128)

Решая мою проблему, я сделал много густого, что указывало мне на А мало Незаменимый Статьи Отказ Но так же велика, как они, они все были написаны без помощи решающего аспекта связи в сегодняшнем дне и возрасте.

То есть: все они были написаны без помощи эмоджи.

Итак, чтобы воспользоваться этой ситуацией, я решил написать свое собственное руководство для понимания Unicode, с большим количеством лица и значков, оказываемых по пути? ✌?.

Перед погружением в технические детали давайте начнем с забавного вопроса. Какой твой любимый эмодзи?

Мой это ” лицо с открытым ртом “, который похож на это? – с одной крупной оговоркой. То, что вы видите, на самом деле зависит от платформы, которую вы используете, чтобы прочитать этот пост!

Посмотрел на моем Mac, эмодзи выглядит как желтый боулинг. На моем планшете Samsung глаза черные и круговые, подчеркиваются белой точкой, которая выдает большую глубину эмоций.

Скопируйте и вставьте emoji (?) В Twitter, и вы увидите что-то совершенно другое. Скопируйте и вставьте его в Messenger.com, и вы увидите, почему это мой любимый.

???? Почему они все разные?

Примечание: по состоянию на 9 июля 2018 года: Messenger, кажется, обновил своими значками Emoji, поэтому значок в правом верхнем углу больше не применяется. ?

Эта веселая маленькая загадка – наш сам в мире Unicode, так как Emojis были частью Стандарт Unicode С 2010 года. Помимо предоставления нам Emoji, Unicode важен, потому что это предпочтительный выбор Интернета для согласованного « кодирование, представление и обработка текста ».

Unicode & кодировка: краткий коммер

Как и во многих темах, лучший способ понять Unicode – знать контекст, окружающий его создание – и для этого, Джоэл Спольского Статья требуется чтение.

Кодовые точки

Поскольку мы теперь вошли в мир Unicode, нам нужно сначала диссоциировать эмоджи от удивительно выразительных значков, которые они есть, и связывают их с чем-то гораздо менее захватывающим. Таким образом, вместо того, чтобы думать о Emojis с точки зрения вещей или эмоций, которые они представляют, мы вместо этого мы будем думать о каждом эмодзе как простое число. Этот номер известен как Кодовая точка Отказ

Кодовые точки – это Ключевая концепция Unicode , который был «предназначен для поддержки всемирного взаимодействия, обработки и отображения письменных текстов разнообразных языков … современного мира». Это делает это, связывая практически каждый символ для печати с уникальной кодовой точкой. Вместе эти персонажи составляют Unicode Набор символов Отказ

Кодовые точки обычно записываются в шестнадцатеричном и префиксированном с U + Для обозначения подключения к Unicode, представляющим персонажи из:

  • Экзотические языки, такие как Телугу [ఋ |. Кодовая точка: u + 0c0b]
  • Шахматные символы [♖ |. Кодовая точка: U + 2656]
  • и, конечно, emojis [? |. Кодовая точка: U + 1F64C]

Глифы – это то, что вы видите

Фактическое на экране представление кодовых точек называются глифы ( полное сопоставление кода указывает на глифы, известно как шрифт ) Отказ

В качестве примера , Возьмите это письмо A, которое является кодовой точкой U + 0041 в Unicode. «А», которую вы видите с вашими глазами, это глиф – это выглядит так, как он делает, потому что он делает, потому что он визуализируется с помощью шрифта среднего. Если бы вы изменили шрифт, Times New Roman например, только глиф «A» изменится – базовая кодовая точка не будет.

Глифы – это ответ на нашу маленькую оказываемую тайну. Под капотом все вариации лица с открытым ртом emoji указывают на то же кодовую точку, U + 1F62E , но глиф Представляя, что это зависит от платформы?

Кодовые точки – абстракции

Потому что они ничего не говорят о том, как они оказываются визуально (требуя шрифта и глифа, чтобы «привести их к жизни»), называются кодовые точки – это абстракция.

Но так же, как кодовые точки – это абстракция для конечных пользователей, они также являются абстракциями для компьютеров. Это потому, что кодовые точки требуют Кодировка персонажа Чтобы преобразовать их в одну вещь, которую компьютеры могут интерпретировать: байты. После преобразования в байты точки кода можно сохранить в файлах или отправлять через сеть на другой компьютер? ➡️ ?.

UTF-8 в настоящее время в мире Самый популярный кодирующий персонаж Отказ UTF-8 использует набор правил для преобразования кодовой точки в уникальную последовательность (от 1 до 4) байтов и наоборот. Кодовые точки называются закодирован в последовательность байтов, а последовательности байтов являются декодировано в кодовые точки. Этот стек переполняет пост Объясняет, как работает алгоритм кодирования UTF-8.

Однако, хотя UTF-8 является преобладающим характером, кодированным в мире, он далеко не единственный. Например, UTF-16 представляет собой альтернативное кодирование символов набора символов Unicode. Изображение ниже сравнивает кодировки UTF-8 и UTF-16 нашего Emoji?,

Проблемы возникают, когда один компьютер кодирует точки кода в байты с одним кодировкой, а другой компьютер (или другой процесс на одном компьютере) декодирует эти байты с другим.

К счастью, UTF-8 достаточно повсеместно, чтобы, по большей части, нам не нужно беспокоиться о несоответствующих кодировках характера. Но когда они произойдут, знакомство с упомянутыми концепциями требуется вытащить себя от беспорядка.

Краткая республика

  • Unicode – это коллекция Кодовые очки , которые являются простыми числами, как правило, написанные в шестнадцатеричном и префиксе с U + Отказ Эти кодовые точки отображают карту практически для каждого печатного персонажа с письменных языков по всему миру.
  • Глифы являются физическим проявлением характера. Этот парень ? это глиф. A f ONT это отображение кода указывает на глифы.
  • Чтобы отправить их по сети или сохранить их в файле, символы и их базовые кодовые точки должны быть закодированы в байты. А Кодировка персонажа Содержит детали того, как кодовая точка встроена в последовательность байтов.
  • UTF-8 В настоящее время в мире должен быть народным кодированием персонажей. Учитывая кодовую точку, UTF-8 кодирует это в последовательность байтов. Учитывая последовательность байтов, UTF-8 декодирует это в кодовую точку.

Практический пример

Правильный рендеринг символов Unicode включает в себя пересечение цепочки, начиная от байтов к кодам указывает на глифы.

Давайте теперь будем использовать текстовый редактор, чтобы увидеть практический пример этой цепи – а также типы вопросов, которые могут возникнуть, когда дела идут невыразится. Текстовые редакторы идеальны, потому что они включают все три части сети рендеринга, показанной выше.

ПРИМЕЧАНИЕ. В моем MacO был сделан следующий пример, используя Sublime Text 3. И дать кредиту, когда кредит должен быть связан с: начало этого примера в значительной степени вдохновлен Это пост от Philip Guo, который представил меня на Hexdump команда (и многое другое).

Начнем с текстового файла, содержащего один символ – мое любимое «лицо с открытым ртом» Emoji. Для тех, кто хочет следовать, я принимал этот файл в Github Гист , который вы получаете локально с Curl Отказ

curl https://gist.githubusercontent.com/jzhang621/d7d9eb167f25084420049cb47510c971/raw/e35f9669785d83db864f9d6b21faf03d9e51608d/emoji.txt > emoji.txt

Как мы узнали, для того, чтобы он был сохранен в файл, Emoji был закодирован в байты с использованием кодировки символов. Этот конкретный файл был закодирован с использованием UTF-8, и мы можем использовать Hexdump Команда для изучения фактического байтового содержимого файла.

j|encoding: hexdump emoji.txt0000000 f0 9f 98 ae 0000004

Выход Hexdump Сообщает нам файл содержит 4 байта, каждый из которых написан в шестнадцатеричном. Фактическая последовательность байтов F0 9F 98 AE Соответствует ожидаемой кодированной байтовой последовательности UTF-8, как показано ниже.

Теперь давайте откроем наш файл в Sublime Text, где мы должны увидеть наш сингл? персонаж. Поскольку мы видим ожидаемый глиф, мы можем предположить, что Sublime Text использовал правильный кодировку символов для декодирования этих байтов в точки кода. Давайте подтвердим, открыв консоль V Iew -> Показать Консо le, и проверяющий Th E VI EW Object, который возвышенный текст обнародован как часть его Python API.

>>> view
# returns the encoding currently associated with the file>>> view.encoding()'UTF-8'

С небольшим знанием Python мы также можем найти кодовую точку Unicode, связанную с нашей эмодзи:

# Returns the character at the given position>>> view.substr(0)'?' 
# ord returns an integer representing the Unicode code point of the character (docs)>>> ord(view.substr(0))128558
# convert code point to hexadecimal, and format with U+>>> print('U+%x' % ord(view.substr(0)))U+1f62e

Опять же, как мы ожидали. Это иллюстрирует полный обход цепочки рендеринга Unicode, который участвует:

  • Чтение файла в виде последовательности кодированных байтов UTF-8.
  • Декодирование байтов в точку кода Unicode.
  • рендеринг глифа, связанного с кодовой точкой.

Все идет нормально ?.

Разные байты, такие же эмоджи

Помимо того, чтобы быть моим любимым текстовым редактором, я выбрал Sublime Text для этого примера, потому что он позволяет легко экспериментировать с кодировками символов.

Теперь мы можем сохранить файл с использованием другого кодирования символов. Чтобы сделать это, нажмите Файл -> Сохранить с кодировкой -> UTF -16 быть. (Очень BRI EFLY, UTF-16 – это альтернативное кодирование символов набора символов Unicode. Вместо кодирования наиболее распространенных символов с использованием одного байта, такими как UTF-8, UTF-16 кодирует каждую точку с 1-65536 Две байты. Кодовые точки больше, чем 65536, как и наши emoji , кодируются с использованием суррогатных пары. Будьте готовы для большого Endian).

Когда мы используем Hexdump Чтобы снова осмотреть файл, мы видим, что содержимое байта изменилось.

# (before: UTF-8)j|encoding: hexdump emoji.txt0000000 f0 9f 98 ae 0000004
# (after: UTF-16 BE)j|encoding: hexdump emoji.txt0000000 d8 3d de 2e0000004

Вернуться в возвышенное текст, мы все еще видим то же самое? Персонаж уставился на нас. Сохранение файла с другим кодировкой символов может измениться фактическое содержимое файла, но он также обновил внутреннее представление Sublime Text о том, как интерпретировать эти байты. Мы можем подтвердить, снова выпустив консоль.

>>> view.encoding()'UTF-16 BE'

Отсюда, все остальное одинаково.

>>> view.substr(0)'?' 
>>> ord(view.substr(0))128558
>>> print('U+%x' % ord(view.substr(0)))U+1f62e

Байты, возможно, изменились, но кодовая точка не была – и эмодзи остается прежним.

Те же байты, но что đÿ~®

Время для кодирования “веселья”. Во-первых, давайте перенесем наш файл с помощью UTF-8, потому что он делает для лучшего примера.

Давайте теперь пойдем вперед, используйте Sublime Text, чтобы повторно открыть существующий файл с использованием другого кодирования символов. Под Файл -> Открыть с помощью encod ING, CLI CK вьетнамцы (Windows 12 58), который превращает наш символ Emoji в следующие четыре бессмысленных символов: đÿ~®.

Когда мы нажимаем «Открыть с кодировкой», мы не меняем фактическое содержимое байта файла, а скорее, путь Sublime Text интерпретирует эти байты. Hexdump подтверждает байты одинаковы:

j|encoding: hexdump emoji.txt0000000 f0 9f 98 ae0000004

Чтобы понять, почему мы видим эти бессмысленные персонажи, нам нужно проконсультироваться с Windows-1258 Кодовая страница, которая представляет собой отображение байтов на набор вьетнамских языковых символов. (Подумайте о кодовой странице как таблицу, создаваемую кодировкой символов). Поскольку эта кодовая страница содержит набор символов с использованием менее 255 символов, точки кода каждого символа могут быть выражены в виде десятичного количества от 0 до 255, что в свою очередь может быть закодировано с использованием 1 байта.

Потому что наш сингл? Emoji требует 4 байта, чтобы кодировать с помощью UTF-8, теперь мы видим 4 символа, когда мы интерпретируем файл с кодировкой Windows-1258.

Неправильный выбор кодирования символов оказывает прямое влияние на то, что мы можем видеть и понимать, скрещенные персонажи в непонятный беспорядок.

Теперь, на «веселую» часть, которую я включаю, чтобы добавить немного цвета в Unicode и почему он существует. Перед Unicode существовала много разных кодовых страниц, таких как Windows-1258, каждый с другим способом отображения данных 1 байта данных на 255 символов. Unicode был создан для того, чтобы включить все различные символы всех различных кодовых страниц в одну систему Отказ Другими словами, Unicode является суперсетом Windows-1258, и каждый символ в кодовой странице Windows-1258 имеет Unicode Counterpart Отказ

Фактически, эти аналоги Unicode – это то, что позволяет возвышать текст для преобразования между различными кодировками символов одним щелчком нажатия кнопки. Внутренне, Sublime Text по-прежнему представляет каждый из наших «Windows-1258 декодированных» символов в качестве кодовой точки Unicode, как мы видим ниже, когда мы выстрелите консоль:

>>> view.encoding()'Vietnamese (Windows 1258)'
# Python 3 strings are "immutable sequences of Unicode code points">>> type(view.substr(0))
>>> view.substr(0)'đ'>>> view.substr(1)'Ÿ'>>> view.substr(2)'˜'>>> view.substr(3)'®'
>>> ['U+%04x' % ord(view.substr(x)) for x in range(0, 4)]['U+0111', 'U+0178', 'U+02dc', 'U+00ae']

Это означает, что мы можем повторно сохранить наши 4 бессмысленных символов с использованием UTF-8. Я оставлю это до вас – если вы сделаете это, и можете правильно предсказать полученное Hexdump Из файла, то вы успешно поняли ключевые концепции позади Unicode, точек кода и кодировки символов. ( Используйте эту кодовую страницу UTF-8 . Ответ можно найти в самом конце этой статьи.).

Обертывание

Эффективно работающий с Unicode включает в себя всегда знать, на каком уровне цепочки рендеринга вы работаете. Это всегда спрашивает себя: что у меня есть? Под капотом глифы не имеют ничего, кроме кодовых точек. Если вы работаете с кодами точками, знайте, что эти точки кода должны быть закодированы в байты с кодировкой символов. Если у вас есть последовательность байтов, представляющих текст, знайте, что эти байты бессмыслены, не зная, что кодирование персонажа, которое было использовано, создавайте те байты.

Как и в любой теме компьютерной науки, лучший способ узнать о Unicode – это экспериментировать. Введите символы, играйте с кодировками символов и сделайте прогнозы, которые вы проверяете, используя Hexdump Отказ Хотя я надеюсь, что эта статья объясняет все, что вам нужно знать о UNICODE, я буду более чем счастлив, если это просто подведет вас, чтобы запустить свои собственные эксперименты.

Спасибо за прочтение! ?

Отвечать:

j|encoding: $ hexdump emoji.txt0000000 c4 91 c5 b8 cb 9c c2 ae0000008