Unicode символы более U+FFFF (65535) называют "wide".
Вот полная таблица диапазонов unicode на данный момент:
name | description | range |
---|---|---|
Plane 0 | U+0000…U+FFFF | |
Plane 1 | Supplementary multilingual plane (SMP) | U+10000…U+1FFFF |
Plane 2 | Supplementary ideographic plane (SIP) | U+20000…U+2FFFF |
Planes 3-13 | Unassigned | U+30000…U+DFFFF |
Plane 14 | Supplementary special-purpose plane (SSP) | U+E0000…U+EFFFF |
Planes 15-16 | Supplementary private use area (S PUA A/B) | U+F0000…U+10FFFF |
В частности в SMP находятся emoji символы, например U+1f4a9 = 💩 (тут должен быть 💩, но вы его не увидите скорее всего)
Печально всё в python 2.7. По-умолчанию, внутри используется представление utf-16, которое не может работать с такими символами "по честному" и в unicode типе они становятся двумя "символами" ("суррогатные пары" в UTF-16).
Суррогатные пары лежат в диапазоне 0xD800—0xDFFF.
assert(len(u'\U0001f4a9') == 2)
Трюк с суррогатами сохранит такие символы работающими при таком преобразовании:
str в utf-8 -> unicode -> str в utf-8
Пример см. в test-python-narrow.output
.
Можно, но сложно. Можно собрать python с особым ключом --enable-unicode=ucs4
.
Все ли C расширения правильно будут работать - вопрос.
Для C есть спец. макросы и в идеальном мире всё должно работать.
Подробнее тут - http://legacy.python.org/dev/peps/pep-0261/
Пример: вывода тестового скрипта со специальной сборкой python 2.7 - test-python-wide.output
.
Сравните с narrow! Главное тут:
import sys
assert(sys.maxunicode > 65535)
assert(len(u'\U0001f4a9') == 1)
В 3-й версии всё ок, по-умолчанию она собирается с поддержкой "wide" unicode. Но просто так с 2 на 3 мы перейти не можем.
Пример работы тестового скрипта: test-python3.output
.
Не обязательно. Как я показывал выше суррогаты для того и придумали, чтобы это не ломалось. Пока мы работаем с "строками unicode" (type(my_string) is unicode
) в python - например, взять, покрутить и выдать в xml/json/html через xsl и пр. – всё будет нормально. Если мы начнём строки обрабатывать, например, считать длину, итерироваться по символам и пр. будут проблемы.
Те, кто думают, что utf-8 = utf-16 / 2
– не правы. Это разные способы кодирования. Utf-8 более универсален! Да, он имеет свои недостатки (не выровнен и пр), но он лучше + совместим c ascii (0-127) и не содержит хаков в виде суррогатных пар.