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
reloadHacks 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 byteDies 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 uPrä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 strin Unicode kann auch dann erfolgen, wenn Sie nicht explizit aufrufen unicode().
Die folgenden Szenarien verursachen UnicodeDecodeErrorAusnahmen:
# 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 cafist 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 UnicodeDecodeErrorAusnahme 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 strauf 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 ioModul 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_stringwäre dann für die Weitergabe an Markdown geeignet. Wenn a UnicodeDecodeErroraus 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-typeHeader sollte ein charsetFeld 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 encodingdie entsprechende Codierung ist. Von Python 2.x unterstützte Codecs finden Sie hier: Standardcodierungen . Wenn Sie erhalten, haben UnicodeDecodeErrorSie wahrscheinlich die falsche Codierung.
Das Fleisch des Sandwichs
Arbeiten Sie mit Unicodes wie mit normalen Strs.
Ausgabe
Standardausgabe / Drucken
printschreibt 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 localehandelt 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. PYTHONIOENCODINGUmgebungsvariable kann die Codierung für stdout erzwingen.
Dateien
io.openKann 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 strjetzt ein Unicode-String und der alte strjetzt 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