UnicodeDecodeError: il codec 'utf8' non può decodificare il byte 0x9c


289

Ho un server socket che dovrebbe ricevere caratteri validi UTF-8 dai client.

Il problema è che alcuni client (principalmente hacker) stanno inviando su di esso tutti i tipi di dati sbagliati.

Sono in grado di distinguere facilmente il client originale, ma sto registrando su file tutti i dati inviati in modo da poterlo analizzare in seguito.

A volte ricevo personaggi come questo œche causano l' UnicodeDecodeErrorerrore.

Devo essere in grado di creare la stringa UTF-8 con o senza quei caratteri.


Aggiornare:

Per il mio caso particolare il servizio socket era un MTA e quindi mi aspetto di ricevere solo comandi ASCII come:

EHLO example.com
MAIL FROM: <john.doe@example.com>
...

Stavo registrando tutto questo in JSON.

Quindi alcune persone là fuori senza buone intenzioni hanno deciso di vendere tutti i tipi di spazzatura.

Ecco perché per il mio caso specifico è perfettamente OK rimuovere i caratteri non ASCII.


1
la stringa esce da un file o un socket? potresti inviare esempi di codice su come la stringa viene codificata e decodificata prima di essere inviata tramite il socket / filehandler?
devsnd,

Ho scritto o non ho scritto che la stringa arriva al socket? Ho semplicemente letto la stringa dal socket e con per metterla in un dizionario e poi JSON per inviarla. La funzione JSON non è riuscita a causa di quei caratteri.
transilvlad,

puoi per favore inserire i tuoi dati di esempio del problema
Shubham Sharma,

Risposte:


343

http://docs.python.org/howto/unicode.html#the-unicode-type

str = unicode(str, errors='replace')

o

str = unicode(str, errors='ignore')

Nota: questo eliminerà (ignorerà) i caratteri in questione restituendo la stringa senza di essi.

Per me questo è il caso ideale poiché lo sto usando come protezione contro input non ASCII che non è consentito dalla mia applicazione.

In alternativa: utilizzare il metodo open dal codecsmodulo per leggere nel file:

import codecs
with codecs.open(file_name, 'r', encoding='utf-8',
                 errors='ignore') as fdata:

45
Sì, anche se di solito è una cattiva pratica / pericolosa, perché perderai solo personaggi. Meglio determinare o rilevare la codifica della stringa di input e decodificarla prima in Unicode, quindi codificare come UTF-8, ad esempio:str.decode('cp1252').encode('utf-8')
Ben Hoyt,

In alcuni casi sì, hai ragione, potrebbe causare problemi. Nel mio caso non mi interessa di loro in quanto sembrano essere caratteri extra provenienti da una cattiva formattazione e programmazione dei client che si collegano al mio server socket.
transilvlad,

Questo in realtà aiuta se il contenuto della stringa non è effettivamente valido, nel mio caso '\xc0msterdam'che si trasforma in u'\ufffdmsterdam'con sostituzione
PvdL

3
se sei finito qui perché hai problemi a leggere un file, aprire il file in modalità binaria potrebbe aiutare: open(file_name, "rb")e quindi applicare l'approccio di Ben dai commenti sopra
kristian

la stessa opzione si applica anche a più, ad esempio a "qualcosa.decode ()"
Alexander Stohr

83

Cambiare il motore da C a Python ha fatto il trucco per me.

Il motore è C:

pd.read_csv(gdp_path, sep='\t', engine='c')

Il codec 'utf-8' non può decodificare il byte 0x92 in posizione 18: byte iniziale non valido

Engine is Python:

pd.read_csv(gdp_path, sep='\t', engine='python')

Nessun errore per me.


3
questa è in realtà una buona soluzione. non so perché sia ​​stato sottoposto a downgrade.
ℕʘʘḆḽḘ

Questa potrebbe non essere una buona idea se hai un csvfile enorme . Potrebbe causare un OutOfMemoryerrore o un riavvio automatico del kernel del notebook. Dovresti impostare encodingquesto caso.
LucasBr

1
Risposta eccellente. Grazie. Questo ha funzionato per me. Avevo "?" All'interno di un personaggio a forma di diamante che stava causando il problema. Con gli occhi chiari ho avuto "" "che è pollici. Ho fatto 2 cose per capire. a) df = pd.read_csv ('test.csv', n_rows = 10000). Questo ha funzionato perfettamente senza il motore. Quindi ho incrementato n_rows per capire quale riga ha avuto un errore. b) df = pd.read_csv ('test.csv', engine = 'python'). Questo ha funzionato e ho stampato la riga errata usando df.iloc [36145], questo mi ha stampato il record errato.
Jagannath Banerjee,

1
questo ha funzionato anche per me ... Non sono sicuro di ciò che sta accadendo "sotto il cofano" e se questa è in realtà una soluzione bella / buona / corretta in tutti i casi, ma ha fatto il trucco per me;)
Chrisvdberge

1
Ottima soluzione! Grazie mille.
Pechi,

62

Questo tipo di problema si risolve per me ora che sono passato a Python 3. Non avevo idea che Python 2 stesse semplicemente rovinando qualsiasi problema con la codifica dei file.

Ho trovato questa bella spiegazione delle differenze e di come trovare una soluzione dopo che nessuna delle precedenti ha funzionato per me.

http://python-notes.curiousefficiency.org/en/latest/python3/text_file_processing.html

In breve, per far sì che Python 3 si comporti nel modo più simile possibile a Python 2, utilizzare:

with open(filename, encoding="latin-1") as datafile:
    # work on datafile here

Tuttavia, leggi l'articolo, non esiste una taglia adatta a tutte le soluzioni.


29
>>> '\x9c'.decode('cp1252')
u'\u0153'
>>> print '\x9c'.decode('cp1252')
œ

16
Sono confuso, come hai scelto cp1252? Ha funzionato per me, ma perché? Non lo so e ora mi sono perso: /. Potresti elaborare? Molte grazie ! :)
Cirillo N.

4
Potresti presentare un'opzione che funziona per tutti i personaggi? C'è un modo per rilevare i caratteri che devono essere decodificati in modo da poter implementare un codice più generico? Vedo che molte persone lo stanno guardando e scommetto che scartare non è l'opzione desiderata come è per me.
transilvlad,

Come puoi vedere questa domanda ha abbastanza popolarità. Pensi di poter espandere la tua risposta con una soluzione più generica?
transilvlad,

13
Non esiste una soluzione più generica per "Indovina la roulette di codifica"
Puppy,

5
l'ho trovato usando una combinazione di ricerca web, fortuna e intuizione: cp1252 eraused by default in the legacy components of Microsoft Windows in English and some other Western languages
bolov,

24

Ho avuto lo stesso problema con UnicodeDecodeErrore l'ho risolto con questa linea. Non so se è il modo migliore ma ha funzionato per me.

str = str.decode('unicode_escape').encode('utf-8')

13

il primo, utilizzando get_encoding_type per ottenere il tipo di file di codifica:

import os    
from chardet import detect

# get file encoding type
def get_encoding_type(file):
    with open(file, 'rb') as f:
        rawdata = f.read()
    return detect(rawdata)['encoding']

il secondo, aprendo i file con il tipo:

open(current_file, 'r', encoding = get_encoding_type, errors='ignore')

1
cosa succede quando ritorna None
Chop Labalagun il

3

Nel caso in cui qualcuno abbia lo stesso problema. Sto usando vim con YouCompleteMe , non sono riuscito ad avviare ycmd con questo messaggio di errore, quello che ho fatto è: export LC_CTYPE="en_US.UTF-8"il problema è sparito.


2
Come si collega questo a questa domanda?
transilvlad

1
Esattamente lo stesso, se sai come funziona youcompleteme. Il plug-in Ycm è architettura socket, la comunicazione tra client e server utilizza socket, entrambi sono moduli Python, non sono in grado di decodificare i pacchetti se l'impostazione di codifica non è corretta
workplaylifecycle

Ho lo stesso problema. Potete per favore dirmi dove mettere export LC_CTYPE="en_US.UTF-8"?
Reman,

@Remonn ciao, sai che abbiamo un file di profilo per bash? Metti dentro.
workplaylifecycle,

@hylepo, sono su un sistema Windows :)
Reman,

3

Cosa puoi fare se devi apportare una modifica a un file, ma non conosci la codifica del file? Se sai che la codifica è compatibile ASCII e desideri solo esaminare o modificare le parti ASCII, puoi aprire il file con il gestore degli errori surrogateescape:

with open(fname, 'r', encoding="ascii", errors="surrogateescape") as f:
    data = f.read()

0

Ho risolto questo problema semplicemente aggiungendo

df = pd.read_csv(fileName,encoding='latin1')
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.