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 como u'\xc4pple'), uno debe decodificar desde la codificación nativa ( iso8859-1/ latin1, a menos que se modifique con lasys.setdefaultencoding función enigmática ) y unicodeluego codificar a un conjunto de caracteres que pueda mostrar los caracteres que desee, en este caso yo lo recomendaría UTF-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"
>>> tell_me_about(v)
(<type 'str'>, '\xc4pple')
>>> v
'\xc4pple'
>>> print v
?pple
Decodificación de una cadena iso8859-1: convierta una cadena simple a unicode
>>> uv = v.decode("iso-8859-1")
>>> uv
u'\xc4pple'
>>> tell_me_about(uv)
(<type 'unicode'>, u'\xc4pple')
>>> print v.decode("iso-8859-1")
Äpple
>>> v.decode('iso-8859-1') == u'\xc4pple'
True
Un poco más de ilustración: con "Ä"
>>> u"Ä" == u"\xc4"
True
>>> "Ä" == u"\xc4"
False
>>> "Ä".decode('utf8') == u"\xc4"
True
>>> "Ä" == "\xc4"
False
Codificación a UTF
>>> u8 = v.decode("iso-8859-1").encode("utf-8")
>>> u8
'\xc3\x84pple'
>>> 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
>>> print u8.decode('utf-8')
Äpple
>>> print u16
���pple
>>> print u16.decode('utf16')
Äpple
>>> v == u8
False
>>> v.decode('iso8859-1') == u8
False
>>> u8.decode('utf-8') == v.decode('latin1') == u16.decode('utf-16')
True
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:
- un tipo
stres un conjunto de bytes, que puede tener una de varias codificaciones, como Latin-1, UTF-8 y UTF-16
- un tipo
unicodees 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)
- el
printcomando tiene su propia lógica para codificar , configurado sys.stdout.encodingy predeterminado en UTF-8
- Uno debe decodificar un
stra 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: