UnicodecodeError, ongeldige voortzettingsbyte

Waarom mislukt het onderstaande item? en waarom lukt het wel met "latin-1" codec?

o = "a test of \xe9 char" #I want this to remain a string as this is what I am receiving
v = o.decode("utf-8")

resulteert in:

 Traceback (most recent call last):  
 File "<stdin>", line 1, in <module>  
 File "C:\Python27\lib\encodings\utf_8.py",
 line 16, in decode
     return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError:
 'utf8' codec can't decode byte 0xe9 in position 10: invalid continuation byte
Oplossing

In het binair ziet 0xE9 er uit als 1110 1001. Als je leest over UTF-8 op Wikipedia, zie je dat zo'n byte moet worden gevolgd door twee van de vorm 10xx xxxx. Dus, bijvoorbeeld:

>>> b'\xe9\x80\x80'.decode('utf-8')
u'\u9000'

Maar dat is slechts de mechanische oorzaak van de uitzondering. In dit geval heb je een string die vrijwel zeker gecodeerd is in latin 1. Je kunt zien hoe UTF-8 en latin 1 er verschillend uitzien:

>>> u'\xe9'.encode('utf-8')
b'\xc3\xa9'
>>> u'\xe9'.encode('latin-1')
b'\xe9'

(Let op, ik'gebruik hier een mix van Python 2 en 3 representatie. De invoer is geldig in elke versie van Python, maar het is onwaarschijnlijk dat uw Python-interpreter zowel unicode- als bytestrings op deze manier weergeeft).

Commentaren (2)

Het is ongeldig UTF-8. Dat karakter is het e-acute karakter in ISO-Latin1, daarom lukt het wel met die codeset.

Als je'niet weet in welke codeset je strings ontvangt, zit je een beetje in de problemen. Het zou het beste zijn als een enkele codeset (hopelijk UTF-8) zou worden gekozen voor uw protocol/toepassing en dan zou u'gewoon degenen verwerpen die'niet decoderen.

Als je dat niet kunt doen, heb je heuristiek nodig.

Commentaren (1)

Omdat UTF-8 multibyte is en er geen char is die overeenkomt met uw combinatie van \xe9 plus volgende spatie.

Waarom zou het lukken in beide utf-8 en latin-1?

Hier hoe dezelfde zin zou moeten zijn in utf-8:

>>> o.decode('latin-1').encode("utf-8")
'a test of \xc3\xa9 char'
Commentaren (1)