UnicodeDecodeError, byte de continuación no válido


257

¿Por qué falla el siguiente artículo? ¿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

Respuestas:


247

En binario, se ve 0xE9 1110 1001. Si lee sobre UTF-8 en Wikipedia , verá que dicho byte debe ser seguido por 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, tiene una cadena que seguramente está codificada en latin 1. Puede 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'

(Tenga en cuenta que estoy usando una combinación de representación de Python 2 y 3. Aquí. La entrada es válida en cualquier versión de Python, pero es poco probable que su intérprete de Python muestre cadenas de unicode y byte de esta manera).


2
Gracias (y al otro que respondió), tenía la creencia errónea de que los caracteres hasta 255 se convertirían directamente.
RuiDC

Me sale UnicodeEncodeError: 'ascii' codec can't encode characters in position 2-3: ordinal not in range(128)error en el uso.encode(latin-1)
Shiva

234

Tuve el mismo error cuando intenté abrir un archivo csv con 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')

1
¿Esto realmente resuelve el problema? ¿No les dice básicamente a los pandas que ignoren el byte bajando a un estilo de codificación menos complejo?
Yu Chen

61

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 conoce el conjunto de códigos en el que está recibiendo las cadenas, está en problemas. Sería mejor si se eligiera un único conjunto de códigos (con suerte UTF-8) para su protocolo / aplicación y luego simplemente rechazaría los que no decodificaron.

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


2
Y para la heurística, vea la biblioteca de chardet.
mlissner

44

Debido a que UTF-8 es multibyte y no hay caracteres correspondientes a su combinación de \xe9más espacio siguiente.

¿Por qué debe tener éxito en tanto UTF-8 y latino-1?

Aquí, cómo debería ser la misma oración en utf-8:

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

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

11

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


2
Gracias a esta respuesta, pude evitar el error de UnicodeDecodeError: el códec 'utf-8' no puede decodificar el byte 0xd7 en la posición 2024079: byte de continuación no válido por soup = BeautifulSoup(open('webpage.html', 'rb'), 'html.parser')
Isaac Philip

6

Esto también me sucedió a mí mientras estaba leyendo un texto que contenía hebreo de un .txtarchivo.

Hice clic: file -> save asy guardé este archivo como UTF-8codificación


5

El error de código utf-8 generalmente se produce cuando el rango de valores numéricos que excede de 0 a 127.

La razón para plantear esta excepción es:

1) Si el punto de código es <128, cada byte es el mismo que el valor del punto de código. 2) Si el punto de código es 128 o mayor, la cadena Unicode no se puede representar en esta codificación. (Python genera una excepción UnicodeEncodeError en este caso).

Para superar esto, tenemos un conjunto de codificaciones, la más utilizada es "Latin-1, también conocida como ISO-8859-1"

Entonces, los puntos ISO-8859-1 Unicode 0–255 son idénticos a los valores de Latin-1, por lo que la conversión a esta codificación simplemente requiere convertir puntos de código en valores de bytes; Si se encuentra un punto de código mayor que 255, la cadena no se puede codificar en Latin-1

cuando se produce esta excepción cuando intenta cargar un conjunto de datos, intente utilizar este formato

df=pd.read_csv("top50.csv",encoding='ISO-8859-1')

Agregue la técnica de codificación al final de la sintaxis que luego acepta cargar el conjunto de datos.


Hola y bienvenido a SO! Por favor, editar su respuesta para asegurarse de que mejora las otras respuestas que ya están presentes en esta pregunta.
Hongsy


-1

En este caso, intenté ejecutar un .py que activa una ruta / file.sql.

¡Mi solución fue modificar la codificación del archivo.sql a "UTF-8 sin BOM" y funciona!

Puedes hacerlo con Notepad ++.

Dejaré una parte de mi código.

/ Código /

con = psycopg2.connect (host = sys.argv [1], puerto = sys.argv [2], nombrebd = sys.argv [3], usuario = sys.argv [4], contraseña = sys.argv [5] )

cursor = con.cursor () sqlfile = open (ruta, 'r')

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.