UnicodeDecodeError, byte di continuazione non valido


257

Perché l'articolo sottostante non riesce? e perché ha successo con il codec "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")

risulta 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

Risposte:


247

In binario, sembra 0xE9 1110 1001. Se leggi UTF-8 su Wikipedia , vedrai che tale byte deve essere seguito da due del modulo 10xx xxxx. Quindi, per esempio:

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

Ma questa è solo la causa meccanica dell'eccezione. In questo caso, hai una stringa quasi sicuramente codificata in latino 1. Puoi vedere come UTF-8 e latino 1 sembrano diversi:

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

(Nota, sto usando un mix di rappresentazione Python 2 e 3. Qui. L'input è valido in qualsiasi versione di Python, ma è improbabile che il tuo interprete Python mostri effettivamente sia le stringhe di unicode che quelle di byte in questo modo.)


2
Grazie (e all'altro che ha risposto), avevo la convinzione errata che i caratteri fino a 255 si sarebbero convertiti direttamente.
RuiDC,

Ottengo un UnicodeEncodeError: 'ascii' codec can't encode characters in position 2-3: ordinal not in range(128)errore nell'uso di.encode(latin-1)
Shiva,

234

Ho avuto lo stesso errore quando ho provato ad aprire un file csv con il metodo panda read_csv.

La soluzione era cambiare la codifica in "latin-1":

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

1
Questo in realtà risolve il problema però? Fondamentalmente non dice semplicemente ai panda di ignorare il byte eseguendo il downgrade a uno stile di codifica meno complesso?
Yu Chen

61

È UTF-8 non valido. Quel personaggio è il carattere acuto in ISO-Latin1, motivo per cui riesce con quel set di codici.

Se non conosci il set di codici in cui ricevi le stringhe, sei un po 'nei guai. Sarebbe meglio se un singolo set di codici (si spera UTF-8) fosse scelto per il tuo protocollo / applicazione e poi rifiutassi quelli che non avevano decodificato.

Se non riesci a farlo, avrai bisogno di euristica.


2
E per l'euristica, consultare la libreria chardet.
mlissner,

44

Perché UTF-8 è multibyte e non esiste alcun carattere corrispondente alla tua combinazione di \xe9 più spazio seguente.

Perché dovrebbe avere successo sia in utf-8 che in latino-1?

Ecco come dovrebbe essere la stessa frase in utf-8:

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

Latin-1 è una famiglia di codifica a byte singolo, quindi tutto in esso deve essere definito in UTF-8. Ma perché a volte il Latin-1 vince?
Reihan_amn

11

Se questo errore si verifica quando si manipola un file che è stato appena aperto, verificare se è stato aperto in 'rb'modalità


2
Grazie a questa risposta, è stato in grado di evitare l'errore di, UnicodeDecodeError: il codec 'utf-8' non può decodificare il byte 0xd7 in posizione 2024079: byte di continuazione non valido di soup = BeautifulSoup(open('webpage.html', 'rb'), 'html.parser')
Isaac Philip

6

Questo è successo anche a me, mentre leggevo un testo contenente l'ebraico da un .txtfile.

Ho cliccato: file -> save ase ho salvato questo file come UTF-8codifica


5

L'errore del codice utf-8 di solito arriva quando l'intervallo di valori numerici supera 0 a 127.

il motivo per sollevare questa eccezione è:

1) Se il punto di codice è <128, ogni byte è uguale al valore del punto di codice. 2) Se il punto di codice è 128 o superiore, la stringa Unicode non può essere rappresentata in questa codifica. (Python solleva un'eccezione UnicodeEncodeError in questo caso.)

Per ovviare a questo abbiamo una serie di codifiche, la più utilizzata è "Latin-1, noto anche come ISO-8859-1"

Quindi i punti Unicode ISO-8859-1 0–255 sono identici ai valori di Latin-1, quindi la conversione in questa codifica richiede semplicemente la conversione di punti di codice in valori di byte; se viene rilevato un punto di codice maggiore di 255, la stringa non può essere codificata in Latin-1

quando si verifica questa eccezione quando si tenta di caricare un set di dati, provare a utilizzare questo formato

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

Aggiungi la tecnica di codifica alla fine della sintassi che accetta quindi di caricare il set di dati.


Ciao e benvenuto in SO! Si prega di modificare la risposta per garantire che essa migliora altre risposte già presenti in questa domanda.
hongsy, il


-1

In questo caso, ho provato ad eseguire un .py che attiva un percorso / file.sql.

La mia soluzione è stata quella di modificare la codifica del file.sql in "UTF-8 senza BOM" e funziona!

Puoi farlo con Notepad ++.

lascerò una parte del mio codice.

/ Codice /

con = psycopg2.connect (host = sys.argv [1], port = sys.argv [2], dbname = sys.argv [3], user = sys.argv [4], password = sys.argv [5] )

cursore = con.cursor () sqlfile = open (path, 'r')

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.