Как мне трактовать строку ASCII как юникод и убирать экранированные символы в ней в python?
Вопрос
Например, если у меня есть строка unicode , я могу закодировать ее как строку ASCII , например так:
>>> u'\u003cfoo/\u003e'.encode('ascii')
'<foo/>'
Однако у меня есть, например, эта ASCII строка:
'\u003foo\u003e'
... которую я хочу превратить в ту же строку ASCII , что и в моем первом примере выше:
'<foo/>'
Решение
Мне потребовалось некоторое время, чтобы разобраться с этим, но эту страницу был лучший ответ:
>>> s = '\u003cfoo/\u003e'
>>> s.decode( 'unicode-escape' )
u'<foo/>'
>>> s.decode( 'unicode-escape' ).encode( 'ascii' )
'<foo/>'
Также имеется кодек «raw-unicode-escape» для обработки другого способа указания строк Unicode - проверьте " Конструкторы Unicode " раздел связанной страницы для получения более подробной информации (так как я не так уж Unicode-Saavy).
РЕДАКТИРОВАТЬ: см. также стандартные кодировки Python . р>
Другие советы
Нед Бэтчелдер сказал:
Это немного опасно в зависимости от того, откуда исходит строка, но как насчет:
>>> s = '\u003cfoo\u003e' >>> eval('u"'+s.replace('"', r'\"')+'"').encode('ascii') '<foo>'
На самом деле этот метод можно сделать безопасным, вот так:
>>> s = '\u003cfoo\u003e'
>>> s_unescaped = eval('u"""'+s.replace('"', r'\"')+'-"""')[:-1]
Обратите внимание на строку с тройными кавычками и черту перед закрывающими 3-кавычками.
<Ол>Таким образом, не нужно беспокоиться о том, что вводят пользователи, если они записаны в необработанном формате.
В Python 2.5 правильная кодировка - "unicode_escape", а не "unicode-escape" (обратите внимание на подчеркивание).
Я не уверен, что более новая версия Python изменила имя юникода, но здесь работал только с подчеркиванием. Р>
Во всяком случае, это оно.
В какой-то момент у вас возникнут проблемы, когда вы встретите специальные символы, такие как китайские символы или смайлики, в строке, которую вы хотите декодировать, т.е. ошибки, которые выглядят следующим образом:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 109-123: ordinal not in range(128)
Для моего случая (обработка данных в твиттере) я расшифровал его следующим образом, чтобы я мог видеть все символы без ошибок
>>> s = '\u003cfoo\u003e'
>>> s.decode( 'unicode-escape' ).encode( 'utf-8' )
>>> <foo>
Это немного опасно в зависимости от того, откуда берется строка, но как насчет:
>>> s = '\u003cfoo\u003e'
>>> eval('u"'+s.replace('"', r'\"')+'"').encode('ascii')
'<foo>'