UnicodeDecodeError, byte de continuación no válido


¿Por qué falla el siguiente elemento? ¿y por qué tiene éxito con el códec" latin-1"?

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
Author: bgporter, 2011-04-05

5 answers

En binario, 0xE9 se parece a 1110 1001. Si lee acerca de UTF-8 en Wikipedia , verá que dicho byte debe ir seguido de dos de la forma 10xx xxxx. Así, 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, tienes una cadena que es casi seguro que está codificada en latín 1. Puedes ver cómo UTF-8 y latin 1 se ven diferentes:

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

(Nota, 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 poco probable que su intérprete Python muestre realmente cadenas unicode y byte de esta manera.)

 177
Author: Josh Lee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-05 16:56:41

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

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

pd.read_csv('ml-100k/u.item', sep='|', names=m_cols , encoding='latin-1')
 113
Author: Mazen Aly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-08 18:13:40

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

Si no conoces el conjunto de códigos en el que estás recibiendo cadenas, estás en un pequeño problema. Sería mejor si se eligiera un solo conjunto de códigos (con suerte UTF-8) para su protocolo/aplicación y luego rechazara los que no decodificaran.

Si no puedes hacer eso, necesitarás heurística.

 48
Author: Sami J. Lehtinen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-05 13:35:21

Porque UTF-8 es multibyte y no hay caracteres correspondientes a su combinación de \xe9 más el espacio siguiente.

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

Aquí cómo debe ser la misma oración en utf-8:

>>> o.decode('latin-1').encode("utf-8")
'a test of \xc3\xa9 char'
 35
Author: neurino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-05 13:28:50

Si este error surge al manipular un archivo que acaba de abrirse, compruebe si lo abrió en modo 'rb'

 1
Author: Patrick Mutuku,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-04 23:09:08