UnicodeDecodeError: il codec "ascii" non può decodificare il byte 0xd1 nella posizione 2: ordinale non compreso nell'intervallo (128)


107

Sto tentando di lavorare con un set di dati molto grande che contiene alcuni caratteri non standard. Devo usare Unicode, secondo le specifiche del lavoro, ma sono sconcertato. (E molto probabilmente sbagliando tutto.)

Apro il CSV utilizzando:

 15     ncesReader = csv.reader(open('geocoded_output.csv', 'rb'), delimiter='\t', quotechar='"')

Quindi, provo a codificarlo con:

name=school_name.encode('utf-8'), street=row[9].encode('utf-8'), city=row[10].encode('utf-8'), state=row[11].encode('utf-8'), zip5=row[12], zip4=row[13],county=row[25].encode('utf-8'), lat=row[22], lng=row[23])

Sto codificando tutto tranne lat e lng perché questi devono essere inviati a un'API. Quando eseguo il programma per analizzare il set di dati in ciò che posso utilizzare, ottengo il seguente Traceback.

Traceback (most recent call last):
  File "push_into_db.py", line 80, in <module>
    main()
  File "push_into_db.py", line 74, in main
    district_map = buildDistrictSchoolMap()
  File "push_into_db.py", line 32, in buildDistrictSchoolMap
    county=row[25].encode('utf-8'), lat=row[22], lng=row[23])
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd1 in position 2: ordinal not in range(128)

Penso di doverti dire che sto usando python 2.7.2 e questo fa parte di un'app costruita su django 1.4. Ho letto diversi post su questo argomento, ma nessuno sembra essere applicabile direttamente. Qualsiasi aiuto sarà molto apprezzato.

Potresti anche voler sapere che alcuni dei caratteri non standard che causano il problema sono Ñ e forse É.


1
Qual è la codifica del file originale? Penso che dovresti decodificarlo secondo la codifica originale e poi convertirlo in utf 8
xiao 啸

l'eventuale duplicato di Encoding dà "il codec 'ascii' non può codificare il carattere ... ordinale non compreso nell'intervallo (128)" [Ed .: e anche di circa uno zilione di altri, ne sono sicuro.]
Karl Knechtel,

Risposte:


152

Unicode non è uguale a UTF-8. Quest'ultimo è solo una codifica per il primo.

Lo stai facendo nel modo sbagliato. Stai leggendo dati con codifica UTF-8 , quindi devi decodificare la stringa con codifica UTF-8 in una stringa Unicode.

Quindi sostituisci .encodecon .decode, e dovrebbe funzionare (se il tuo .csv è codificato in UTF-8).

Niente di cui vergognarsi, però. Scommetto che 3 programmatori su 5 hanno avuto difficoltà a capirlo all'inizio, se non di più;)

Aggiornamento: se i tuoi dati di input non sono codificati UTF-8, allora devi farlo .decode()con la codifica appropriata, ovviamente. Se non viene fornito nulla, python assume ASCII, che ovviamente fallisce sui caratteri non ASCII.


1
Il motivo dell'errore è che Python sta tentando di decodificarlo automaticamente dalla codifica predefinita, ASCII, in modo che possa quindi codificarlo come specificato, in UTF-8. Poiché i dati non sono ASCII validi, non funziona.
agf

7
certo, ma se si tratta di dati codificati in UTF8 (come immagino), allora .decode('utf-8')dovrebbe fare il trucco, né?
ch3ka

Certo, probabilmente hai ragione. Stavo solo spiegando perché ottieni quell'errore specifico in questa situazione.
agf

1
Perfetto! Grazie mille. Quindi risulta che era .decode ('latin-1') - questo ha senso perché era Ñ che mi stava dando il problema. Ancora! Grazie!
jelkimantis

La tua soluzione funziona per alcuni casi, ma nel caso in cui lo uso, ricevo un altro errore Il codec "ascii" non può codificare il carattere u "\ xf1" nella posizione 2: ordinale non compreso nell'intervallo (128)
Vikash Mishra

84

Aggiungi semplicemente queste righe ai tuoi codici:

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

5
`AttributeError: il modulo 'sys' non ha l'attributo 'setdefaultencoding' non sembra funzionare in Python 3
skjerns

Woot woot! Questo mi ha aiutato.
Shougo Makishima

1
Funziona per il mio Python 2.7, nota, è necessario ricaricare (sys), altrimenti la codifica setdefaultencoding non sarebbe accessibile.
Yu Shen

1
Questa è stata l'unica cosa che ha fatto funzionare per me su molte domande SO. Grazie mille!
Freedo

il nome 'reload' non è definito
Davide

28

per gli utenti di Python 3. tu puoi fare

with open(csv_name_here, 'r', encoding="utf-8") as f:
    #some codes

funziona anche con il pallone :)


1
È la prima volta che ho aiutato qualcuno qui. è bello sapere che ho aiutato :)
Skrmnghrd

1
E hai aiutato anche a me :) Tutte le altre risposte non hanno funzionato per la lettura dei file. Ora devo scoprire come risolverlo anche in scrittura;)
user2194898

puoi inviarmi il link del tuo codice? Cercherò di aiutare
Skrmnghrd

9

Il motivo principale dell'errore è che la codifica predefinita assunta da python è ASCII. Quindi, se i dati della stringa da codificare encode('utf8')contengono caratteri che sono al di fuori dell'intervallo ASCII, ad esempio per una stringa come 'hgvcj 터 파크 387', python genererebbe un errore perché la stringa non è nel formato di codifica previsto.

Se stai utilizzando una versione di python precedente alla 3.5, una soluzione affidabile sarebbe impostare la codifica predefinita assunta da python su utf8:

import sys
reload(sys)
sys.setdefaultencoding('utf8')
name = school_name.encode('utf8')

In questo modo Python sarebbe in grado di anticipare i caratteri all'interno di una stringa che non rientrano nell'intervallo ASCII.

Tuttavia, se stai usando python versione 3.5 o successiva, la funzione reload () non è disponibile, quindi dovresti aggiustarla usando decode eg

name = school_name.decode('utf8').encode('utf8')

qual è la differenza tra la tua risposta e la mia
khelili miliana

1
Più dettagliato. Le persone spesso trovano utili i dettagli causali. E il tuo codice funziona, nessuna deroga prevista.
Temi Fakunle

1
reload è disponibile in Python 3, dovresti solo importarlo. from imp import reload
Meow

@Meow ma non c'è sys.setdefaultencoding in Python 3. Quindi, nel contesto della compatibilità py2 \ py3, qualche controllo andrà bene, sys.getdefaultencoding () forse. Apprezzerei un consiglio in merito. stackoverflow.com/questions/28127513/...
Konst54

2

Per gli utenti di Python 3:

la modifica della codifica da "ascii" a "latin1" funziona.

Inoltre, puoi provare a trovare la codifica automaticamente leggendo i primi 10000 byte utilizzando lo snippet di seguito:

import chardet  
with open("dataset_path", 'rb') as rawdata:  
            result = chardet.detect(rawdata.read(10000))  
print(result)

2

Il mio computer aveva l'impostazione locale sbagliata.

L'ho fatto per primo

>>> import locale
>>> locale.getpreferredencoding(False)
'ANSI_X3.4-1968'

locale.getpreferredencoding(False)è la funzione chiamata da open()quando non si fornisce una codifica . L'output dovrebbe essere 'UTF-8', ma in questo caso è una variante di ASCII .

Quindi ho eseguito il comando bash localee ho ottenuto questo output

$ locale
LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

Quindi, stavo usando la locale Ubuntu predefinita, che fa sì che Python apra i file come ASCII invece di UTF-8. Ho dovuto impostare la mia localizzazione suen_US.UTF-8

sudo apt install locales 
sudo locale-gen en_US en_US.UTF-8    
sudo dpkg-reconfigure locales

Se non puoi modificare il sistema locale a livello di sistema, puoi invocare tutto il tuo codice Python in questo modo:

PYTHONIOENCODING="UTF-8" python3 ./path/to/your/script.py

o fare

export PYTHONIOENCODING="UTF-8"

per impostarlo nella shell in cui lo esegui.


1

se si verifica questo problema durante l'esecuzione di certbot durante la creazione o il rinnovo del certificato, utilizzare il metodo seguente

grep -r -P '[^\x00-\x7f]' /etc/apache2 /etc/letsencrypt /etc/nginx

Quel comando ha trovato il carattere offensivo "´" in un file .conf nel commento. Dopo averlo rimosso (puoi modificare i commenti come desideri) e ricaricato nginx, tutto ha funzionato di nuovo.

Fonte: https://github.com/certbot/certbot/issues/5236


0

O quando gestisci il testo in Python se è un testo Unicode, prendi nota che è Unicode.

Imposta text=u'unicode text'invece solo text='unicode text'.

Questo ha funzionato nel mio caso.


0

aperto con codifica UTF 16 a causa di lat e long.

with open(csv_name_here, 'r', encoding="utf-16") as f:

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.