UnicodeDecodeError, geçersiz devam baytı

Aşağıdaki öğe neden başarısız oluyor? ve neden "latin-1" codec ile başarılı oluyor?

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")

Sonuçlar:

 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
Çözüm

İkili sistemde 0xE9, 1110 1001 gibi görünür. Eğer Wikipedia'da UTF-8 hakkında okursanız, böyle bir baytın ardından 10xx xxxx şeklinde iki bayt gelmesi gerektiğini görürsünüz. Yani, örneğin:

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

Ancak bu sadece istisnanın mekanik nedenidir. Bu durumda, neredeyse kesinlikle latin 1 ile kodlanmış bir dizgiye sahipsiniz. UTF-8 ve latin 1'in nasıl farklı göründüğünü görebilirsiniz:

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

(Burada Python 2 ve 3 temsillerinin bir karışımını kullandığımı unutmayın. Girdi Python'un herhangi bir sürümünde geçerlidir, ancak Python yorumlayıcınızın hem unicode hem de byte dizelerini bu şekilde göstermesi pek olası değildir).

Yorumlar (2)

UTF-8 geçersizdir. Bu karakter ISO-Latin1'deki e-acute karakteridir, bu yüzden bu kod kümesiyle başarılı olur.

Eğer dizeleri aldığınız kod kümesini bilmiyorsanız, başınız biraz dertte demektir. Protokolünüz/uygulamanız için tek bir kod kümesi (umarım UTF-8) seçmeniz ve ardından kodu çözülemeyenleri reddetmeniz en iyisi olacaktır.

Eğer bunu yapamıyorsanız, sezgisel yöntemlere ihtiyacınız olacaktır.

Yorumlar (1)

Çünkü UTF-8 çok baytlıdır ve \xe9 artı aşağıdaki boşluk kombinasyonunuza karşılık gelen bir karakter yoktur.

Neden hem utf-8 hem de latin-1'de başarılı olmalıdır?

Burada aynı cümle utf-8'de nasıl olmalıdır:

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