C'est un problème courant, voici donc une illustration relativement complète.
Pour les chaînes non-unicode (c'est-à-dire celles sans upréfixe comme u'\xc4pple'), il faut décoder à partir du codage natif ( iso8859-1/ latin1, sauf si modifié avec lasys.setdefaultencoding fonction énigmatique ) vers unicode, puis encoder dans un jeu de caractères qui peut afficher les caractères que vous souhaitez, dans ce cas je Je recommande UTF-8.
Tout d'abord, voici une fonction utilitaire pratique qui vous aidera à éclairer les modèles de chaîne Python 2.7 et d'Unicode:
>>> def tell_me_about(s): return (type(s), s)
Une corde simple
>>> v = "\xC4pple"
>>> tell_me_about(v)
(<type 'str'>, '\xc4pple')
>>> v
'\xc4pple'
>>> print v
?pple
Décoder une chaîne iso8859-1 - convertir une chaîne simple en 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 peu plus d'illustration - avec «Ä»
>>> u"Ä" == u"\xc4"
True
>>> "Ä" == u"\xc4"
False
>>> "Ä".decode('utf8') == u"\xc4"
True
>>> "Ä" == "\xc4"
False
Encodage en 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')
Relation entre unicode et UTF et 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
Exceptions 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)
On pourrait les contourner en convertissant l'encodage spécifique (latin-1, utf8, utf16) en unicode par exemple u8.decode('utf8').encode('latin1').
Alors peut-être pourrait-on tirer les principes et généralisations suivants:
- un type
strest un ensemble d'octets, qui peut avoir l'un des nombreux codages tels que Latin-1, UTF-8 et UTF-16
- un type
unicodeest un ensemble d'octets qui peuvent être convertis en n'importe quel nombre d'encodages, le plus souvent UTF-8 et latin-1 (iso8859-1)
- la
printcommande a sa propre logique d'encodage , définie sur sys.stdout.encodinget par défaut sur UTF-8
- Il faut décoder un
stren unicode avant de le convertir en un autre encodage.
Bien sûr, tout cela change dans Python 3.x.
J'espère que c'est éclairant.
Lectures complémentaires
Et les diatribes très illustratives d'Armin Ronacher: