2009-07-24 24 views
19

Tengo un problema con las cadenas que obtengo de uno de mis clientes a través de xmlrpc. Me envía cadenas utf8 que están codificadas dos veces :(así que cuando las obtengo en python tengo un objeto Unicode que tiene que decodificarse una vez más, pero obviamente Python no lo permite. He notado que mi cliente sin embargo necesito hacer solución rápida por ahora antes de que lo fijaDescodificación de doble codificación de utf8 en Python

cadena cruda de volcado TCP:.

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

esto se convierte en:

u'Rafa\xc5\x82' 

La mejor lo que tenemos es:

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

Esto se traduce en cadena correcta, que es:

u'Rafa\u0142' 

esto funciona sin embargo es feo como el infierno y no se puede utilizar en el código de producción. Si alguien sabe cómo solucionar este problema de una manera más adecuada, por favor escriba. Gracias, Chris

Respuesta

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

@partisann: ¡Claro! No sabía acerca de raw_unicode_escape (obviamente 8-) – RichieHindle

+0

Gracias partidista, tampoco lo sé. –

+1

¡Que su reputación crezca más allá de lo esperado, incluso después de todos esos años! :) – Marian

3

Yow, que fue muy divertido!

>>> 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' 

por lo que la primera decodificación, para conseguir una cadena Unicode, donde cada personaje es en realidad un valor de byte UTF-8. Vaya a través del valor entero de cada uno de esos caracteres para volver a una cadena UTF-8 genuina, que luego decodificará como normal.

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

latin1 es solo una abreviatura del método de Richie's nuts'n'bolts.

Es muy curioso que el códec raw_unicode_escape gravemente descrito da el mismo resultado que latin1 en este caso. ¿Siempre dan el mismo resultado? Si es así, ¿por qué tener un códec de este tipo? De lo contrario, sería preferible saber con certeza cómo el cliente del OP hizo la transformación de 'Rafa\xc5\x82' a u'Rafa\xc5\x82' y luego invertir ese proceso exactamente; de ​​lo contrario, podríamos despegarnos si aparecen datos diferentes antes de que se corrija la doble codificación.

+2

Cuando la cadena contiene solo los puntos de código 0-255, siempre es igual. Las diferencias son caracteres superiores a eso; raw_unicode_escape escapará de ellos, por ejemplo. \ u1234, donde latin1 lanzará UnicodeEncodeError. (La decodificación tiene la diferencia simétrica - raw_unicode_escape decodes \ u1234 escapa, latin1 no, pero aquí solo está codificando.) Son equivalentes aquí, pero me quedaría con latin1, ya que esto tiene nada que ver con escapar y latin1 es una codificación más ampliamente comprendida. –

+0

Gracias Glenn, pensando en las barras invertidas después de medianoche, mi cerebro se convirtió en una calabaza :-) –

Cuestiones relacionadas