tl; dr / schnelle Lösung
- Nicht ohne weiteres dekodieren / kodieren
- Gehen Sie nicht davon aus, dass Ihre Zeichenfolgen UTF-8-codiert sind
- Versuchen Sie, Zeichenfolgen so schnell wie möglich in Ihrem Code in Unicode-Zeichenfolgen zu konvertieren
- Korrigieren Sie Ihr Gebietsschema: Wie löse ich UnicodeDecodeError in Python 3.6?
- Seien Sie nicht versucht, schnelle
reload
Hacks zu verwenden
Unicode Zen in Python 2.x - Die lange Version
Ohne die Quelle zu sehen, ist es schwierig, die Grundursache zu kennen, daher muss ich allgemein sprechen.
UnicodeDecodeError: 'ascii' codec can't decode byte
Dies geschieht im Allgemeinen, wenn Sie versuchen, eine Python 2.x-Datei str
, die kein ASCII enthält, in eine Unicode-Zeichenfolge zu konvertieren, ohne die Codierung der ursprünglichen Zeichenfolge anzugeben.
Kurz gesagt, Unicode-Zeichenfolgen sind ein völlig separater Typ von Python-Zeichenfolgen, der keine Codierung enthält. Sie enthalten nur Unicode- Punktcodes und können daher jeden Unicode-Punkt aus dem gesamten Spektrum enthalten. Zeichenfolgen enthalten codierten Text, zB UTF-8, UTF-16, ISO-8895-1, GBK, Big5 usw. Zeichenfolgen werden in Unicode dekodiert und Unicodes werden in Zeichenfolgen codiert . Dateien und Textdaten werden immer in codierten Zeichenfolgen übertragen.
Die Autoren des Markdown-Moduls verwenden wahrscheinlich unicode()
(wo die Ausnahme ausgelöst wird) als Qualitätsgatter für den Rest des Codes - es konvertiert ASCII oder umschließt vorhandene Unicodes-Zeichenfolgen erneut in eine neue Unicode-Zeichenfolge. Die Markdown-Autoren können die Codierung der eingehenden Zeichenfolge nicht kennen. Sie müssen daher Zeichenfolgen in Unicode-Zeichenfolgen dekodieren, bevor Sie sie an Markdown übergeben.
Unicode-Zeichenfolgen können in Ihrem Code mit dem u
Präfix für Zeichenfolgen deklariert werden . Z.B
>>> my_u = u'my ünicôdé strįng'
>>> type(my_u)
<type 'unicode'>
Unicode-Zeichenfolgen können auch aus Dateien, Datenbanken und Netzwerkmodulen stammen. In diesem Fall müssen Sie sich keine Gedanken über die Codierung machen.
Fallstricke
Die Konvertierung von str
in Unicode kann auch dann erfolgen, wenn Sie nicht explizit aufrufen unicode()
.
Die folgenden Szenarien verursachen UnicodeDecodeError
Ausnahmen:
# Explicit conversion without encoding
unicode('€')
# New style format string into Unicode string
# Python will try to convert value string to Unicode first
u"The currency is: {}".format('€')
# Old style format string into Unicode string
# Python will try to convert value string to Unicode first
u'The currency is: %s' % '€'
# Append string to Unicode
# Python will try to convert string to Unicode first
u'The currency is: ' + '€'
Beispiele
In der folgenden Abbildung sehen Sie, wie das Wort café
je nach Terminaltyp entweder in "UTF-8" - oder "Cp1252" -Codierung codiert wurde. In beiden Beispielen caf
ist nur reguläres ASCII. In UTF-8 é
wird mit zwei Bytes codiert. In "Cp1252" ist é 0xE9 (was auch der Unicode-Punktwert ist (es ist kein Zufall)). Das Richtige decode()
wird aufgerufen und die Konvertierung in einen Python-Unicode ist erfolgreich:
In diesem Diagramm decode()
wird mit aufgerufen ascii
(was dem Aufrufen unicode()
ohne angegebene Codierung entspricht). Da ASCII keine Bytes größer als enthalten kann 0x7F
, wird eine UnicodeDecodeError
Ausnahme ausgelöst:
Das Unicode-Sandwich
Es wird empfohlen, in Ihrem Code ein Unicode-Sandwich zu erstellen, in dem Sie alle eingehenden Daten in Unicode-Zeichenfolgen dekodieren, mit Unicodes arbeiten und str
auf dem Weg nach draußen in s codieren . Dies erspart Ihnen die Sorge um die Codierung von Zeichenfolgen in der Mitte Ihres Codes.
Eingabe / Dekodierung
Quellcode
Wenn Sie Nicht-ASCII in Ihren Quellcode backen müssen, erstellen Sie einfach Unicode-Zeichenfolgen, indem Sie der Zeichenfolge ein Präfix voranstellen u
. Z.B
u'Zürich'
Damit Python Ihren Quellcode dekodieren kann, müssen Sie einen Codierungsheader hinzufügen, der der tatsächlichen Codierung Ihrer Datei entspricht. Wenn Ihre Datei beispielsweise als 'UTF-8' codiert wäre, würden Sie Folgendes verwenden:
# encoding: utf-8
Dies ist nur erforderlich, wenn Ihr Quellcode Nicht-ASCII enthält .
Dateien
Normalerweise werden Nicht-ASCII-Daten aus einer Datei empfangen. Das io
Modul bietet einen TextWrapper, der Ihre Datei im laufenden Betrieb unter Verwendung eines bestimmten Codes dekodiert encoding
. Sie müssen die richtige Codierung für die Datei verwenden - dies kann nicht leicht erraten werden. Zum Beispiel für eine UTF-8-Datei:
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
my_unicode_string = my_file.read()
my_unicode_string
wäre dann für die Weitergabe an Markdown geeignet. Wenn a UnicodeDecodeError
aus der read()
Zeile stammt, haben Sie wahrscheinlich den falschen Codierungswert verwendet.
CSV-Dateien
Das Python 2.7 CSV-Modul unterstützt keine Nicht-ASCII-Zeichen 😩. Hilfe erhalten Sie jedoch unter https://pypi.python.org/pypi/backports.csv .
Verwenden Sie es wie oben, aber übergeben Sie die geöffnete Datei daran:
from backports import csv
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
for row in csv.reader(my_file):
yield row
Datenbanken
Die meisten Python-Datenbanktreiber können Daten in Unicode zurückgeben, erfordern jedoch normalerweise eine kleine Konfiguration. Verwenden Sie für SQL-Abfragen immer Unicode-Zeichenfolgen.
MySQL
Fügen Sie in der Verbindungszeichenfolge Folgendes hinzu:
charset='utf8',
use_unicode=True
Z.B
>>> db = MySQLdb.connect(host="localhost", user='root', passwd='passwd', db='sandbox', use_unicode=True, charset="utf8")
PostgreSQL
Hinzufügen:
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
HTTP
Webseiten können in nahezu jeder Codierung codiert werden. Der Content-type
Header sollte ein charset
Feld enthalten , das auf die Codierung hinweist. Der Inhalt kann dann manuell gegen diesen Wert dekodiert werden. Alternativ gibt Python-Requests Unicodes in zurück response.text
.
Manuell
Wenn Sie Zeichenfolgen manuell dekodieren müssen, können Sie einfach tun my_string.decode(encoding)
, wo encoding
die entsprechende Codierung ist. Von Python 2.x unterstützte Codecs finden Sie hier: Standardcodierungen . Wenn Sie erhalten, haben UnicodeDecodeError
Sie wahrscheinlich die falsche Codierung.
Das Fleisch des Sandwichs
Arbeiten Sie mit Unicodes wie mit normalen Strs.
Ausgabe
Standardausgabe / Drucken
print
schreibt durch den stdout-Stream. Python versucht, einen Encoder auf stdout so zu konfigurieren, dass Unicodes mit der Codierung der Konsole codiert werden. Wenn es sich beispielsweise um eine Linux-Shell locale
handelt en_GB.UTF-8
, wird die Ausgabe in codiert UTF-8
. Unter Windows sind Sie auf eine 8-Bit-Codepage beschränkt.
Eine falsch konfigurierte Konsole, z. B. ein beschädigtes Gebietsschema, kann zu unerwarteten Druckfehlern führen. PYTHONIOENCODING
Umgebungsvariable kann die Codierung für stdout erzwingen.
Dateien
io.open
Kann genau wie die Eingabe verwendet werden, um Unicodes transparent in codierte Byte-Zeichenfolgen zu konvertieren.
Datenbank
Mit derselben Konfiguration zum Lesen können Unicodes direkt geschrieben werden.
Python 3
Python 3 ist nicht mehr Unicode-fähig als Python 2.x, ist jedoch in Bezug auf das Thema etwas weniger verwirrt. ZB ist der reguläre str
jetzt ein Unicode-String und der alte str
jetzt bytes
.
Die Standardcodierung ist UTF-8. Wenn Sie also .decode()
eine Byte-Zeichenfolge ohne Angabe einer Codierung verwenden, verwendet Python 3 die UTF-8-Codierung. Dies behebt wahrscheinlich 50% der Unicode-Probleme.
Arbeitet außerdem open()
standardmäßig im Textmodus, gibt also dekodierte str
(Unicode- Rückgaben ) zurück. Die Codierung wird von Ihrem Gebietsschema abgeleitet, das auf Un * x-Systemen in der Regel UTF-8 oder auf Windows-Boxen eine 8-Bit-Codepage wie Windows-1251 ist.
Warum sollten Sie nicht verwenden sys.setdefaultencoding('utf8')
Es ist ein böser Hack (es gibt einen Grund, den Sie verwenden müssen reload
), der nur Probleme maskiert und Ihre Migration zu Python 3.x behindert. Verstehen Sie das Problem, beheben Sie die Grundursache und genießen Sie Unicode Zen. Siehe Warum sollten wir sys.setdefaultencoding ("utf-8") NICHT in einem py-Skript verwenden? für weitere Details