2012-02-14 4 views
3

unichr(0x10000) с ошибкой ValueError, когда cpython скомпилирован без --enable-unicode=ucs4.дополнительные коды для строки unicode в python

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

+0

Я уверен, что этого не может быть сделано, и что это одна из причин, по которым вы не можете доверять чужому Python для работы на произвольных данных Unicode. Однако это, похоже, исправлено в версии v3.3. Если вам нужен абстрактный Unicode, вам нужно подождать следующей версии или использовать более надежную платформу. – tchrist

+0

@tchrist, спасибо. Да. Мне нужно изучить Python3.x. Кажется, он исправит множество источников путаницы. –

+0

Я (в основном) не согласен с @tchrist, что это невозможно сделать; см. мой ответ ниже, где я это делаю. –

ответ

8

Да, здесь вы идете:

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

Решающий момент, чтобы понять, что unichr() преобразует целое число в единый блок кода в строках кодирования интерпретатора Python. The Python Standard Library documentation for 2.7.3, 2. Built-in Functions, on unichr() читает,

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

Я добавил акцент на «один символ», которым они обозначают "one code unit" in Unicode terms.

Я предполагаю, что вы используете Python 2.x. У интерпретатора Python 3.x нет встроенной функции unichr(). Вместо этого The Python Standard Library documentation for 3.3.0, 2. Built-in Functions, on chr() читает,

Возвращает строки, представляющая символ которого Юникод элемента кода является целым числом я .... Допустимый диапазон для аргумента от 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 intepreter с кодировкой UTF-32 для строк Unicode. Тем не менее, он должен работать без изменений на любом интерпретаторе Python 2.x с любой реализацией строки Unicode.

+0

Хороший ответ. Обратите внимание, что последняя версия Python избавилась от всей проблемы «большой сборки», что также очень помогает этим вещам. Если вы используете более раннюю версию, вы обязательно должны использовать «широкую сборку». – tchrist

+0

Вы вправе указать код 2.x. Спасибо за указатели на спецификации и объяснение различий между ними. –

Смежные вопросы