Как обрабатывать строку ASCII как unicode и unescape экранированные символы в ней в python?

Например, если у меня есть строка в Юникоде, я могу кодировать ее как строку ASCII, например:

>>> u'\u003cfoo/\u003e'.encode('ascii')
'<foo/>'

Однако у меня есть, например, эта строка ASCII:

'\u003foo\u003e'

... что я хочу превратиться в ту же строку ASCII, что и в первом примере выше:

'<foo/>'

Ответ 1

Мне потребовалось некоторое время, чтобы понять это, но эта страница получила лучший ответ:

>>> s = '\u003cfoo/\u003e'
>>> s.decode( 'unicode-escape' )
u'<foo/>'
>>> s.decode( 'unicode-escape' ).encode( 'ascii' )
'<foo/>'

Там также есть кодек "raw-unicode-escape", который обрабатывает другой способ указания строк Unicode. Более подробную информацию см. в разделе "Конструкторы Unicode" на связанной странице (поскольку я не являюсь Unicode-saavy).

EDIT: см. также Стандартные кодировки Python.

Ответ 2

Нед Батчелдер сказал:

Это немного опасно в зависимости от того, откуда идет строка, но как насчет:

>>> s = '\u003cfoo\u003e'
>>> eval('u"'+s.replace('"', r'\"')+'"').encode('ascii')
'<foo>'

На самом деле этот метод можно сделать безопасным следующим образом:

>>> s = '\u003cfoo\u003e'
>>> s_unescaped = eval('u"""'+s.replace('"', r'\"')+'-"""')[:-1]

Обратите внимание на строку тройной кавычки и тире прямо перед закрытием 3-кавычек.

  • Использование 3-кавычной строки гарантирует, что если пользователь вводит "\\" (пробелы, добавленные для визуальной ясности) в строку, это не нарушит оценщика;
  • Фишка в конце является отказоустойчивой, если пользовательская строка заканчивается символом "\". Перед тем, как назначить результат, мы нарезаем вставленную черту с помощью [: -1]

Таким образом, не нужно беспокоиться о том, что вводит пользователь, если оно будет записано в необработанном формате.

Ответ 3

В Python 2.5 правильная кодировка - "unicode_escape", а не "unicode-escape" (обратите внимание на подчеркивание).

Я не уверен, изменила ли новая версия Python имя юникода, но здесь работала только с подчеркиванием.

Во всяком случае, это он.

Ответ 4

В какой-то момент вы столкнетесь с проблемами, когда сталкиваетесь с особыми символами, такими как китайские символы или смайлики, в строке, которую вы хотите декодировать, то есть ошибки, которые выглядят следующим образом:

UnicodeEncodeError: 'ascii' codec can't encode characters in position 109-123: ordinal not in range(128)

В моем случае (обработка данных twitter) я декодировался следующим образом, чтобы разрешить мне видеть все символы без ошибок

>>> s = '\u003cfoo\u003e'
>>> s.decode( 'unicode-escape' ).encode( 'utf-8' )
>>> <foo>

Ответ 5

Это немного опасно в зависимости от того, откуда идет строка, но как насчет:

>>> s = '\u003cfoo\u003e'
>>> eval('u"'+s.replace('"', r'\"')+'"').encode('ascii')
'<foo>'