2011-04-05 13 views
133

¿Por qué está fallando el elemento siguiente? y por qué tiene éxito con el códec "latin-1"?UnicodeDecodeError, byte de continuación no válido

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

resultados en:

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 

Respuesta

145

En binario, 0xE9 parece 1110 1001. Si lee UTF-8 on Wikipedia, verá que dicho byte debe ir seguido de dos del formulario 10xx xxxx. Entonces, por ejemplo:

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

Pero esa es solo la causa mecánica de la excepción. En este caso, usted tiene una cadena que está casi seguro que codifica en América 1. Se puede ver cómo UTF-8 y latino 1 aspecto diferente:

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

(Tenga en cuenta, estoy usando una mezcla de Python 2 y 3 representación aquí. La entrada es válida en cualquier versión de Python, pero es improbable que tu intérprete de Python muestre cadenas de bytes y unicode de esta manera.)

+1

Gracias (y para el otro que respondió), estaba bajo la creencia errónea de que los caracteres hasta 255 convertirían directamente. – RuiDC

44

Es UTF-8 válido. Ese personaje es el personaje e-agudo en ISO-Latin1, por lo que tiene éxito con ese conjunto de códigos.

Si no conoce el conjunto de códigos que está recibiendo en cadenas, que está en un poco de problemas. Sería mejor si se escogiera un solo conjunto de códigos (con suerte UTF-8) para su protocolo/aplicación y luego simplemente rechazaría los que no se decodificaron.

Si no puede hacer eso, necesitará heurística.

+19

+1 para decir lo que el personaje es. – meshy

+2

Y para la heurística, consulte la biblioteca chardet. – mlissner

33

Debido a UTF-8 es de varios bytes y no hay carbón que corresponde a su combinación de \xe9 más espacio siguiente.

¿Por qué debería tener éxito en ambos utf-8 y latin-1?

Aquí la forma en la misma frase debe estar en UTF-8:

+0

Latin-1 es una familia de codificación de un solo byte, por lo que todo en él debe definirse en UTF-8. Pero ¿por qué alguna vez gana Latin-1? –

64

Tuve el mismo error cuando intenté abrir un archivo csv por pandas read_csv método.

La solución fue cambiar la codificación a 'latino-1':

pd.read_csv('ml-100k/u.item', sep='|', names=m_cols , encoding='latin-1') 
Cuestiones relacionadas