2012-05-02 17 views
60

Sto tentando di utilizzare un set di dati molto grande che contiene caratteri non standard. Ho bisogno di usare unicode, come da specifiche del lavoro, ma sono sconcertato. (E molto probabilmente facendo tutto sbagliato.)UnicodeDecodeError: il codec 'ascii' non può decodificare il byte 0xd1 in posizione 2: ordinale non compreso nell'intervallo (128)

apro il CSV utilizzando:

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

Poi, tento di codificare 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 codifica tutto tranne il 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 che dovrei dirvi che sto usando python 2.7.2, e questo fa parte di un app costruire su Django 1.4. Ho letto diversi post su questo argomento, ma nessuno di essi sembra applicarsi direttamente. Qualsiasi aiuto sarà molto apprezzato.

Si potrebbe anche voler sapere che alcuni dei caratteri non standard che causano il problema sono Ñ e possibilmente É.

+1

Qual è la sua codifica del file originale? Penso che dovresti decodificarlo secondo la codifica originale e poi convertire in utf 8 –

+0

possibile duplicato di [Encoding give "'codec ascii' non può codificare caratteri ... ordinal not in range (128)"] (http: // stackoverflow .com/questions/2513027/encoding-give-ascii-codec-cant-encode-character-ordinal-not-in-range128) [Ed .: e di circa un miliardo di altri anche, sono sicuro.] –

risposta

119

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

Lo stai facendo nel modo sbagliato. Tu sei leggendo UTF-8- codificato dati, quindi devi decodificare la stringa codificata UTF-8 in una stringa unicode.

Quindi basta sostituire .encode con .decode e dovrebbe funzionare (se il tuo .csv è codificato in UTF-8).

Nulla di cui vergognarsi. Scommetto 3 a 5 i programmatori hanno avuto problemi in un primo momento la comprensione questo, se non di più;)

Aggiornamento: Se i dati di input è non codifica UTF-8, poi si deve .decode() con la codifica appropriata, naturalmente . Se non viene fornito nulla, python assume ASCII, che ovviamente fallisce su caratteri non ASCII.

+0

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

+7

sicuro, ma se si tratta di dati codificati * UTF8- * (come immagino), quindi '.decode ('utf-8')' dovrebbe fare il trucco, né? – ch3ka

+0

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

48

Basta aggiungere queste righe ai codici:

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

grazie, questa fissa il mio problema –

+0

'AttributeError: module 'sys' non ha alcun attributo 'setdefaultencoding' non sembra funzionare in Python 3 – skjerns

1

Il motivo principale per l'errore è che la codifica di default assunto da pitone è ASCII. Quindi, se i dati di stringa da codificare di encode('utf8') contengono caratteri che non rientrano nell'intervallo ASCII, ad es. per una stringa come 'hgvcj 터 파크 387', python genererebbe un errore perché la stringa non è nel formato di codifica previsto.

Se si utilizza la versione di Python precedenti alla versione 3.5, una correzione affidabile sarebbe quella di impostare la codifica di default assunta da python a utf8:

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

In questo modo pitone sarebbe in grado di anticipare i caratteri all'interno di una stringa che non rientrano nel range ASCII.

Tuttavia, se si utilizza Python versione 3.5 o versione successiva, la funzione reload() non è disponibile, quindi dovresti risolverlo usando la decodifica, ad es.

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

qual è la differenza tra la risposta e la mia –

+0

Altro dettagliata. Le persone spesso trovano utili i dettagli causali. E il tuo codice funziona bene, non è prevista alcuna deroga. –

+0

reload è disponibile in Python 3 dovresti solo importarlo. da imp import ricarica – Meow

2

per utenti Python 3. si può fare

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

funziona con la boccetta troppo :)

+0

grazie signore! che ha risolto il mio problema – fuzunspm

+0

È stata la prima volta che ho aiutato qualcuno qui. si sente bene sapendo che ho aiutato :) – screaminghard

Problemi correlati