Дополнительные кодовые точки к строке юникода в python

unichr(0x10000) терпит неудачу с ValueError когда cpython компилируется без --enable-unicode=ucs4,

Существует ли встроенная функция языка или библиотеки ядра, которая преобразует произвольное скалярное значение Юникода или кодовую точку в unicode Строка, которая работает независимо от того, на каком интерпретаторе Python работает программа?

1 ответ

Решение

Да, вот, пожалуйста

>>> unichr(0xd800)+unichr(0xdc00)
u'\U00010000'

Важно понять, что unichr() преобразует целое число в единицу кода в строковом кодировании интерпретатора Python. Документация по стандартной библиотеке Python для 2.7.3, 2. Встроенные функции, наunichr() читает,

Вернуть строку Unicode одного символа, чей код Unicode является целым числом i.... Допустимый диапазон для аргумента зависит от конфигурации Python - это может быть либо UCS2 [0..0xFFFF], либо UCS4 [0..0x10FFFF]. ValueError поднимается иначе.

Я добавил акцент на "один символ", под которым они понимаются как "одна единица кода" в терминах Юникода.

Я предполагаю, что вы используете Python 2.x. Интерпретатор Python 3.x не имеет встроенного unichr() функция. Вместо этого стандартная библиотека Python для 3.3.0, 2. Встроенные функции, наchr() читает,

Вернуть строку, представляющую символ, чья кодовая точка Unicode является целым числом i.... Допустимый диапазон для аргумента - от 0 до 1 114 111 (0x10FFFF в базе 16).

Обратите внимание, что возвращаемое значение теперь является строкой неопределенной длины, а не строкой с одной единицей кода. Так в Python 3.x, chr(0x10000) будет вести себя так, как вы ожидали. Он "преобразует произвольное скалярное значение Юникода или кодовую точку в unicode строка, которая работает независимо от того, на каком интерпретаторе python запущена программа ".

Но вернемся к Python 2.x. Если вы используете unichr() создать Python 2.x unicode объекты, и вы используете скалярные значения Unicode выше 0xFFFF, тогда вы делаете свой код осведомленным о реализации интерпретатора Python unicode объекты.

Вы можете изолировать это осознание с помощью функции, которая пытается unichr() по скалярному значению, ловит ValueErrorи пытается снова с соответствующей суррогатной парой UTF-16:

def unichr_supplemental(scalar):
     try:
         return unichr(scalar)
     except ValueError:
         return unichr( 0xd800 + ((scalar-0x10000)//0x400) ) \
               +unichr( 0xdc00 + ((scalar-0x10000)% 0x400) )

>>> unichr_supplemental(0x41),len(unichr_supplemental(0x41))
(u'A', 1)
>>> unichr_supplemental(0x10000), len(unichr_supplemental(0x10000))
(u'\U00010000', 2)

Но вам может оказаться проще просто преобразовать ваши скаляры в 4-байтовые значения UTF-32 в байте UTF-32. stringи декодировать этот байт string в unicode строка:

>>> '\x00\x00\x00\x41'.decode('utf-32be'), \
... len('\x00\x00\x00\x41'.decode('utf-32be'))
(u'A', 1)
>>> '\x00\x01\x00\x00'.decode('utf-32be'), \
... len('\x00\x01\x00\x00'.decode('utf-32be'))
(u'\U00010000', 2)

Приведенный выше код был протестирован на Python 2.6.7 с кодировкой UTF-16 для строк Unicode. Я не тестировал его на интерпретаторе Python 2.x с кодировкой UTF-32 для строк Unicode. Однако он должен работать без изменений на любом интерпретаторе Python 2.x с любой реализацией строки Unicode.

Другие вопросы по тегам