J'ai cette chaîne qui a été décodée de Quoted-printable à ISO-8859-1 avec le module email. Cela me donne des chaînes comme "\ xC4pple" qui correspondraient à "Äpple" (Apple en suédois). Cependant, je ne peux pas convertir ces chaînes en 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)
Que devrais-je faire?
python
character-encoding
Zyberzero
la source
la source
C'est un problème courant, voici donc une illustration relativement complète.
Pour les chaînes non-unicode (c'est-à-dire celles sans
u
préfixe commeu'\xc4pple'
), il faut décoder à partir du codage natif (iso8859-1
/latin1
, sauf si modifié avec lasys.setdefaultencoding
fonction énigmatique ) versunicode
, puis encoder dans un jeu de caractères qui peut afficher les caractères que vous souhaitez, dans ce cas je Je recommandeUTF-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" # 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 "?".
Décoder une chaîne iso8859-1 - convertir une chaîne simple en 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 start
Un peu plus d'illustration - avec «Ä»
>>> 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').
Encodage en 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')
Relation entre unicode et UTF et 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)
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:
str
est un ensemble d'octets, qui peut avoir l'un des nombreux codages tels que Latin-1, UTF-8 et UTF-16unicode
est 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)print
commande a sa propre logique d'encodage , définie sursys.stdout.encoding
et par défaut sur UTF-8str
en 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:
la source
Pour Python 3:
bytes(apple,'iso-8859-1').decode('utf-8')
J'ai utilisé ceci pour un texte incorrectement encodé en iso-8859-1 (montrant des mots comme VeÅ \ x99ejné ) au lieu de utf-8. Ce code produit la version correcte Veřejné .
la source
bytes
vient-il?r = requests.get(url)
puis le réglage direct ar.encoding = 'utf-8'
fonctionné pour moiDécodez en Unicode, encodez les résultats en UTF8.
apple.decode('latin1').encode('utf8')
la source
concept = concept.encode('ascii', 'ignore') concept = MySQLdb.escape_string(concept.decode('latin1').encode('utf8').rstrip())
Je fais ça, je ne suis pas sûr que ce soit une bonne approche mais ça marche à chaque fois !!
la source