Tengo esta cadena que ha sido decodificada de Quoted-printable a ISO-8859-1 con el módulo de correo electrónico. Esto me da cadenas como "\ xC4pple" que correspondería a "Äpple" (Apple en sueco). Sin embargo, no puedo convertir esas cadenas a UTF-8.
>>> apple = "\xC4pple"
>>> apple
'\xc4pple'
>>> apple.encode("UTF-8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 0: ordinal not in range(128)
¿Qué tengo que hacer?
python
character-encoding
Zyberzero
fuente
fuente

Este es un problema común, por lo que aquí hay una ilustración relativamente completa.
Para cadenas no Unicode (es decir, aquellas sin
uprefijo comou'\xc4pple'), uno debe decodificar desde la codificación nativa (iso8859-1/latin1, a menos que se modifique con lasys.setdefaultencodingfunción enigmática ) yunicodeluego codificar a un conjunto de caracteres que pueda mostrar los caracteres que desee, en este caso yo lo recomendaríaUTF-8.Primero, aquí hay una función de utilidad útil que ayudará a iluminar los patrones de cadena de Python 2.7 y Unicode:
>>> def tell_me_about(s): return (type(s), s)Una cuerda simple
>>> v = "\xC4pple" # iso-8859-1 aka latin1 encoded string >>> tell_me_about(v) (<type 'str'>, '\xc4pple') >>> v '\xc4pple' # representation in memory >>> print v ?pple # map the iso-8859-1 in-memory to iso-8859-1 chars # note that '\xc4' has no representation in iso-8859-1, # so is printed as "?".Decodificación de una cadena iso8859-1: convierta una cadena simple a unicode
>>> uv = v.decode("iso-8859-1") >>> uv u'\xc4pple' # decoding iso-8859-1 becomes unicode, in memory >>> tell_me_about(uv) (<type 'unicode'>, u'\xc4pple') >>> print v.decode("iso-8859-1") Äpple # convert unicode to the default character set # (utf-8, based on sys.stdout.encoding) >>> v.decode('iso-8859-1') == u'\xc4pple' True # one could have just used a unicode representation # from the startUn poco más de ilustración: con "Ä"
>>> u"Ä" == u"\xc4" True # the native unicode char and escaped versions are the same >>> "Ä" == u"\xc4" False # the native unicode char is '\xc3\x84' in latin1 >>> "Ä".decode('utf8') == u"\xc4" True # one can decode the string to get unicode >>> "Ä" == "\xc4" False # the native character and the escaped string are # of course not equal ('\xc3\x84' != '\xc4').Codificación a UTF
>>> u8 = v.decode("iso-8859-1").encode("utf-8") >>> u8 '\xc3\x84pple' # convert iso-8859-1 to unicode to utf-8 >>> tell_me_about(u8) (<type 'str'>, '\xc3\x84pple') >>> u16 = v.decode('iso-8859-1').encode('utf-16') >>> tell_me_about(u16) (<type 'str'>, '\xff\xfe\xc4\x00p\x00p\x00l\x00e\x00') >>> tell_me_about(u8.decode('utf8')) (<type 'unicode'>, u'\xc4pple') >>> tell_me_about(u16.decode('utf16')) (<type 'unicode'>, u'\xc4pple')Relación entre unicode y UTF y latin1
>>> print u8 Äpple # printing utf-8 - because of the encoding we now know # how to print the characters >>> print u8.decode('utf-8') # printing unicode Äpple >>> print u16 # printing 'bytes' of u16 ���pple >>> print u16.decode('utf16') Äpple # printing unicode >>> v == u8 False # v is a iso8859-1 string; u8 is a utf-8 string >>> v.decode('iso8859-1') == u8 False # v.decode(...) returns unicode >>> u8.decode('utf-8') == v.decode('latin1') == u16.decode('utf-16') True # all decode to the same unicode memory representation # (latin1 is iso-8859-1)Excepciones Unicode
>>> u8.encode('iso8859-1') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128) >>> u16.encode('iso8859-1') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0: ordinal not in range(128) >>> v.encode('iso8859-1') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 0: ordinal not in range(128)Uno podría evitarlos convirtiendo de la codificación específica (latin-1, utf8, utf16) a Unicode, por ejemplo
u8.decode('utf8').encode('latin1').Entonces, tal vez uno podría dibujar los siguientes principios y generalizaciones:
stres un conjunto de bytes, que puede tener una de varias codificaciones, como Latin-1, UTF-8 y UTF-16unicodees un conjunto de bytes que se puede convertir a cualquier número de codificaciones, más comúnmente UTF-8 y latin-1 (iso8859-1)printcomando tiene su propia lógica para codificar , configuradosys.stdout.encodingy predeterminado en UTF-8stra unicode antes de convertirlo a otra codificación.Por supuesto, todo esto cambia en Python 3.x.
Espero que sea esclarecedor.
Otras lecturas
Y las muy ilustrativas peroratas de Armin Ronacher:
fuente
Para Python 3:
bytes(apple,'iso-8859-1').decode('utf-8')Usé esto para un texto codificado incorrectamente como iso-8859-1 (que muestra palabras como VeÅ \ x99ejnà © ) en lugar de utf-8. Este código produce la versión correcta Veřejné .
fuente
bytesviener = requests.get(url)y luego la configuración directar.encoding = 'utf-8'funcionó para míDecodificar a Unicode, codificar los resultados a UTF8.
apple.decode('latin1').encode('utf8')fuente
concept = concept.encode('ascii', 'ignore') concept = MySQLdb.escape_string(concept.decode('latin1').encode('utf8').rstrip())Hago esto, no estoy seguro de si es un buen enfoque, ¡pero funciona siempre!
fuente