UnicodeDecodeError: Der Codec 'ascii' kann das Byte 0xd1 an Position 2 nicht dekodieren: Ordnungszahl nicht im Bereich (128)


107

Ich versuche, mit einem sehr großen Datensatz zu arbeiten, der einige nicht standardmäßige Zeichen enthält. Ich muss Unicode gemäß den Jobspezifikationen verwenden, bin aber verblüfft. (Und möglicherweise alles falsch machen.)

Ich öffne die CSV mit:

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

Dann versuche ich es zu codieren mit:

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])

Ich codiere alles außer lat und lng, weil diese an eine API gesendet werden müssen. Wenn ich das Programm ausführe, um den Datensatz in das zu analysieren, was ich verwenden kann, erhalte ich den folgenden 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)

Ich denke, ich sollte Ihnen sagen, dass ich Python 2.7.2 verwende, und dies ist Teil einer App, die auf Django 1.4 basiert. Ich habe mehrere Beiträge zu diesem Thema gelesen, aber keiner von ihnen scheint direkt zuzutreffen. Jede Hilfe wird sehr geschätzt.

Vielleicht möchten Sie auch wissen, dass einige der nicht standardmäßigen Zeichen, die das Problem verursachen, Ñ und möglicherweise É sind.


1
Was ist Ihre ursprüngliche Dateicodierung? Ich denke, Sie sollten es gemäß der ursprünglichen Codierung dekodieren und dann in utf 8
xiao 2

Ein mögliches Duplikat der Codierung ergibt "'ascii' Codec kann kein Zeichen codieren ... Ordnungszahl nicht im Bereich (128)" [Hrsg.: und von ungefähr einer Million anderen, da bin ich mir sicher.]
Karl Knechtel

Antworten:


152

Unicode ist nicht gleich UTF-8. Letzteres ist nur eine Kodierung für Ersteres.

Du machst es falsch herum. Sie lesen UTF-8- codierte Daten, daher müssen Sie den UTF-8-codierten String in einen Unicode-String decodieren .

So ersetzen Sie einfach .encodemit .decode, und es sollte funktionieren (wenn Ihre CSV - UTF-8-codiert).

Nichts, wofür man sich schämen müsste. Ich wette, 3 von 5 Programmierern hatten Probleme, dies zuerst zu verstehen, wenn nicht mehr;)

Update: Wenn Ihre Eingabedaten nicht UTF-8-codiert sind, müssen Sie .decode()natürlich die entsprechende Codierung verwenden. Wenn nichts angegeben ist, geht Python von ASCII aus, was bei Nicht-ASCII-Zeichen offensichtlich fehlschlägt.


1
Der Grund für den Fehler ist, dass Python versucht, ihn automatisch von der Standardcodierung ASCII zu dekodieren, damit er ihn dann wie angegeben in UTF-8 codieren kann. Da die Daten kein gültiges ASCII sind, funktioniert es nicht.
agf

7
Sicher, aber wenn es sich um UTF8- codierte Daten handelt (wie ich denke), .decode('utf-8')sollte man dann den Trick machen, noch?
ch3ka

Sicher, du hast wahrscheinlich recht. Ich habe nur erklärt, warum Sie in dieser Situation diesen speziellen Fehler bekommen.
agf

1
Perfekt! Vielen Dank. Es stellt sich also heraus, dass es sich um .decode ('latin-1') handelte - dies ist sinnvoll, weil es Ñ war, das mir das Problem bereitete. Nochmal! Danke dir!
Jelkimantis

Ihre Lösung funktioniert in einigen Fällen, aber wenn ich diese verwende, erhalte ich einen weiteren Fehler: 'ascii' Codec kann das Zeichen u '\ xf1' in Position 2 nicht codieren: Ordnungszahl nicht im Bereich (128)
Vikash Mishra

83

Fügen Sie einfach diese Zeilen zu Ihren Codes hinzu:

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

5
`AttributeError: Modul 'sys' hat kein Attribut 'setdefaultencoding' scheint in Python 3 nicht zu funktionieren
skjerns

Woot woot! Das hat mir geholfen.
Shougo Makishima

1
Es funktioniert für mein Python 2.7, beachten Sie, dass ein erneutes Laden (sys) erforderlich ist, andernfalls wäre auf setdefaultencoding nicht zugegriffen werden können.
Yu Shen

1
Das war das einzige, was mich aus vielen SO-Fragen heraus zum Laufen gebracht hat. Vielen Dank!
Freedo

Name 'reload' ist nicht definiert
Davide

28

für Python 3 Benutzer. du kannst tun

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

es funktioniert auch mit flasche :)


1
Es ist das erste Mal, dass ich jemandem hier geholfen habe. fühlt sich gut an zu wissen, dass ich geholfen habe :)
Skrmnghrd

1
Und du hast mir auch geholfen :) Alle anderen Antworten funktionierten nicht beim Lesen von Dateien. Jetzt muss ich herausfinden, wie ich es auch zum Schreiben reparieren kann;)
user2194898

Können Sie mir den Link Ihres Codes senden? Ich werde versuchen zu helfen
Skrmnghrd

9

Der Hauptgrund für den Fehler ist, dass die von Python angenommene Standardcodierung ASCII ist. Wenn die zu codierenden Zeichenfolgendaten encode('utf8')Zeichen enthalten, die außerhalb des ASCII-Bereichs liegen, z. B. für eine Zeichenfolge wie 'hgvcj 파크 파크 387', würde Python einen Fehler auslösen, da die Zeichenfolge nicht das erwartete Codierungsformat aufweist.

Wenn Sie eine frühere Python-Version als Version 3.5 verwenden, besteht eine zuverlässige Lösung darin, die von Python angenommene Standardcodierung auf Folgendes festzulegen utf8:

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

Auf diese Weise kann Python Zeichen innerhalb einer Zeichenfolge antizipieren, die außerhalb des ASCII-Bereichs liegen.

Wenn Sie jedoch Python Version 3.5 oder höher verwenden, ist die Funktion reload () nicht verfügbar, sodass Sie sie mithilfe der Dekodierung beheben müssen, z

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

Was ist der Unterschied zwischen Ihrer Antwort und meiner
Khelili Miliana

1
Genauer. Menschen finden kausale Details oft hilfreich. Und Ihr Code funktioniert übrigens, keine Abweichung beabsichtigt.
Temi Fakunle

1
reload ist in Python 3 verfügbar, Sie müssten es nur importieren. von imp import reload
Meow

@Meow, aber es gibt keine sys.setdefaultencoding in Python 3. Im Kontext der Kompatibilität py2 \ py3 reicht also eine Überprüfung aus, sys.getdefaultencoding () vielleicht. Würde mich über einen Ratschlag zu diesem Thema freuen. stackoverflow.com/questions/28127513/…
Konst54

2

Für Python 3-Benutzer:

Das Ändern der Codierung von 'ascii' auf 'latin1' funktioniert.

Sie können auch versuchen, die Codierung automatisch zu finden, indem Sie die oberen 10000 Bytes mithilfe des folgenden Snippets lesen:

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

2

Mein Computer hatte das falsche Gebietsschema eingestellt.

Ich habe es zuerst getan

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

locale.getpreferredencoding(False)ist die Funktion, die aufgerufen wird, open()wenn Sie keine Codierung angeben . Die Ausgabe sollte sein 'UTF-8', aber in diesem Fall handelt es sich um eine Variante von ASCII .

Dann habe ich den Befehl bash ausgeführt localeund diese Ausgabe erhalten

$ 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=

Daher habe ich das Standard-Ubuntu-Gebietsschema verwendet, wodurch Python Dateien als ASCII anstelle von UTF-8 öffnet. Ich musste mein Gebietsschema auf einstellenen_US.UTF-8

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

Wenn Sie das Gebietsschema nicht systemweit ändern können, können Sie Ihren gesamten Python-Code folgendermaßen aufrufen:

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

oder tun

export PYTHONIOENCODING="UTF-8"

Um es in der Shell festzulegen, führen Sie es aus.


1

Wenn dieses Problem beim Ausführen von certbot beim Erstellen oder Erneuern des Zertifikats auftritt, verwenden Sie die folgende Methode

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

Dieser Befehl hat das fehlerhafte Zeichen "´" in einer .conf-Datei im Kommentar gefunden. Nach dem Entfernen (Sie können Kommentare nach Belieben bearbeiten) und dem erneuten Laden von Nginx funktionierte alles wieder.

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


0

Wenn Sie sich mit Text in Python befassen, wenn es sich um einen Unicode-Text handelt, notieren Sie sich, dass es sich um Unicode handelt.

Setze text=u'unicode text'stattdessen einfach text='unicode text'.

Das hat in meinem Fall funktioniert.


0

offen mit Codierung UTF 16 wegen lat und long.

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

0

Es funktioniert, indem nur das Argument 'rb' read binary anstelle von 'r' read verwendet wird

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.