2009-07-24 3 views
19

У меня проблема со строками, которые я получаю от одного из моих клиентов по сравнению с xmlrpc. Он отправляет мне строки utf8, которые закодированы дважды :(Поэтому, когда я получаю их на python, у меня есть объект unicode, который нужно декодировать еще раз, но, очевидно, python этого не позволяет. Я заметил, что мой клиент мне нужен сделать быстрый обходной путь сейчас, прежде чем он фиксирует этоДекодирование с двойной кодировкой utf8 в Python

Raw строка из протокола TCP отвала:.

<string>Rafa\xc3\x85\xc2\x82</string> 

это превращается в:

u'Rafa\xc5\x82' 

лучший мы получаем:

eval(repr(u'Rafa\xc5\x82')[1:]).decode("utf8") 

Это приводит к правильной последовательности, которая:

u'Rafa\u0142' 

это работает, однако это некрасиво, как ад, и не может быть использовано в производстве код. Если кто-нибудь знает, как решить эту проблему более удобным способом, напишите. Спасибо, Крис

ответ

38
 
>>> s = u'Rafa\xc5\x82' 
>>> s.encode('raw_unicode_escape').decode('utf-8') 
u'Rafa\u0142' 
>>> 
+1

@partisann: Аккуратно! Я не знал о raw_unicode_escape (очевидно, 8-) – RichieHindle

+0

Спасибо, партизан, я об этом не знаю. –

+1

Пусть ваша репутация выйдет за рамки ожиданий, даже после всех этих лет! :) – Marian

3

Йоу, это было весело!

>>> original = "Rafa\xc3\x85\xc2\x82" 
>>> first_decode = original.decode('utf-8') 
>>> as_chars = ''.join([chr(ord(x)) for x in first_decode]) 
>>> result = as_chars.decode('utf-8') 
>>> result 
u'Rafa\u0142' 

Таким образом, вы делаете первое декодирование, получая строку Unicode, где каждый символ является фактически значением байта UTF-8. Вы переходите через целочисленное значение каждого из этих символов, чтобы вернуться к подлинной строке UTF-8, которую вы затем декодируете как обычно.

2
>>> weird = u'Rafa\xc5\x82' 
>>> weird.encode('latin1').decode('utf8') 
u'Rafa\u0142' 
>>> 

latin1 - это всего лишь аббревиатура от метода орехового ореха Ричи.

Очень любопытно, что серьезно недооцененный кодек raw_unicode_escape дает тот же результат, что и latin1. Всегда ли они дают одинаковый результат? Если да, то почему такой кодек? В противном случае было бы желательно точно знать, как именно OP-клиент выполнил преобразование от 'Rafa\xc5\x82' до u'Rafa\xc5\x82', а затем, чтобы точно отменить этот процесс, иначе мы могли бы отклеиться, если разные данные появятся до того, как будет установлена ​​двойная кодировка.

+2

Когда ваша строка содержит только кодовые страницы 0-255, она всегда одна и та же. Различия между ними превышают символы: raw_unicode_escape избежит их, например. \ u1234, где latin1 будет вызывать UnicodeEncodeError. (Декодирование имеет симметричную разницу - raw_unicode_escape декодирует \ u1234 escapes, latin1 - нет, но это только кодировка здесь.) Они здесь эквивалентны, но я бы придерживался latin1, так как это не имеет ничего общего с экранированием, а latin1 - более широко понятная кодировка. –

+0

Спасибо Гленн, думая о обратной косой чертой после полуночи, превратил мой мозг в тыкву :-) –

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

  • Нет связанных вопросов^_^