Es gibt mehrere Aspekte dieses Problems. Die grundlegende Frage ist, in welchem Zeichensatz Sie ausgeben möchten. Möglicherweise müssen Sie auch den Eingabezeichensatz herausfinden.
Das Drucken (entweder mit print
oder write
) in eine Datei mit einem expliziten encoding="..."
wandelt die interne Unicode-Repräsentation von Python in diese Codierung um. Wenn die Ausgabe Zeichen enthält, die von dieser Codierung nicht unterstützt werden, erhalten Sie einen UnicodeEncodeError
. Sie können z.B. kein Russisch oder Chinesisch oder Indisch oder Hebräisch oder Arabisch oder Emoji oder ... oder irgendetwas außer einem eingeschränkten Satz von etwa 200+ westlichen Zeichen in eine Datei schreiben, deren Codierung "cp1252"
ist, da dieser begrenzte 8-Bit-Zeichensatz keine Möglichkeit hat, diese Zeichen darzustellen.
Grundsätzlich tritt dasselbe Problem bei jedem 8-Bit-Zeichensatz auf, einschließlich fast aller veralteten Windows-Zeichensätze (437, 850, 1250, 1251 usw.), obwohl einige von ihnen zusätzlich zu oder anstelle von Englisch einige weitere Skriptsprachen unterstützen (1251 unterstützt beispielsweise Kyrillisch, sodass Sie Russisch, Ukrainisch, Serbisch, Bulgarisch usw. schreiben können). Eine 8-Bit-Codierung hat nur maximal 256 Zeichencodes und keine Möglichkeit, ein Zeichen darzustellen, das nicht darunter fällt.
Vielleicht wäre es jetzt eine gute Zeit, Joel Spolskys Das absolute Minimum, das jeder Softwareentwickler unbedingt über Unicode und Zeichencodierungen wissen muss (Keine Ausreden!)
Auf Plattformen, auf denen das Terminal Unicode nicht drucken kann (heutzutage nur noch Windows, obwohl dieses Problem auch auf anderen Plattformen im letzten Jahrtausend weit verbreitet war), kann der Versuch, Unicode-Strings mit print
zu drucken, ebenfalls diesen Fehler verursachen oder zu Mojibake führen. Wenn Sie beispielsweise etwas wie Héllö
anstelle von Héllö
sehen, liegt hier Ihr Problem.
Kurz gesagt, Sie müssen also wissen:
-
Was ist der Zeichensatz der Seite, die Sie gescraped haben, oder der Daten, die Sie erhalten haben? Wurde korrekt gescraped? Hat der Ursprungskontakt seine Codierung korrekt angegeben oder sind Sie anderweitig in der Lage, diese Informationen zu erhalten (oder zu erraten)? Einige Websites geben fälschlicherweise einen anderen Zeichensatz an, als die Seite tatsächlich enthält, einige Websites haben die Verbindung zwischen dem Webserver und einer Datenbank falsch konfiguriert. Siehe z.B. Scrapen mit korrekter Zeichencodierung (Python-Anforderungen + Beautifulsoup) für ein detaillierteres Beispiel mit einigen Lösungen.
-
Welchen Zeichensatz möchten Sie schreiben? Wenn Sie auf den Bildschirm drucken, ist Ihr Terminal korrekt konfiguriert und Ihr Python-Interpreter identisch konfiguriert? Eventuell auch siehe Wie man UTF-8 in der Windows-Konsole anzeigt
Wenn Sie hier sind, ist die Antwort auf eine dieser Fragen wahrscheinlich nicht "UTF-8". Diese Codierung wird zunehmend auch für Webseiten verwendet, obwohl der frühere Standard ISO-8859-1 (auch Latin-1 genannt) war und vor kurzem noch Windows Codepage 1252.
In Zukunft möchten Sie im Grunde genommen, dass alle Ihre textuellen Daten Unicode sind, außergewöhnlich sind einige Randfälle. Im Allgemeinen bedeutet das UTF-8, obwohl auf Windows (oder wenn Sie Java-Kompatibilität benötigen) auch UTF-16 halbwegs praktikabel ist, wenn auch etwas umständlich. (Es gibt mehrere andere Unicode-Serialisierungsformate, die in spezialisierten Fällen nützlich sein können. UTF-32 ist technisch trivial, benötigt jedoch deutlich mehr Speicher; UTF-7 wird in einigen Netzwerkprotokollen verwendet, bei denen 7-Bit-ASCII für den Transport erforderlich ist.) Eventuell auch siehe https://utf8everywhere.org/
Natürlich müssen Sie, wenn Sie in eine Datei drucken, diese Datei auch mit einem Tool untersuchen, das sie korrekt anzeigen kann. Ein häufiger Pilotenfehler ist, die Datei mit einem Tool zu öffnen, das nur die derzeit ausgewählte Systemcodierung anzeigt oder das die Codierung zu erraten versucht, aber falsch liegt. Bei der Anzeige von UTF-8-Text mit der Windows-Codepage 1252 würde beispielsweise Héllö
als Héllö
dargestellt.
Wenn die Codierung von Zeichendaten unbekannt ist, gibt es keine einfache Möglichkeit, sie automatisch festzustellen. Wenn Sie wissen, was der Text darstellen soll, können Sie dies vielleicht ableiten, aber dies ist in der Regel ein manueller Prozess mit einigen Schätzungen (Automatische Tools wie chardet
und ftfy
können helfen, machen aber manchmal Fehler.)
Um festzustellen, welche Codierung Sie betrachten, kann es hilfreich sein, wenn Sie die einzelnen Bytes in einem Zeichen identifizieren können, der nicht korrekt angezeigt wird. Wenn Sie z.B. H\x8ell\x9a
betrachten, es aber als Héllö
erwarten, können Sie die Bytes in einer Übersetzungstabelle nachschlagen. Ich habe eine solche Tabelle unter https://tripleee.github.io/8bit veröffentlicht, wo Sie sehen können, dass es sich in diesem Beispiel wahrscheinlich um einen der veralteten Mac 8-Bit-Zeichensätze handelt; mit weiteren Datenpunkten können Sie es vielleicht auf nur einen von ihnen eingrenzen (und wenn nicht, tut es in der Praxis jeder von ihnen, da alle Codepunkte, die für Sie relevant sind, auf die gleichen Unicode-Zeichen abbilden).
Python 3 auf den meisten Plattformen verwendet standardmäßig für alle Eingaben und Ausgaben UTF-8, auf Windows ist dies jedoch in der Regel nicht der Fall. Dann wird stattdessen standardmäßig die Standardcodierung des Systems verwendet (in einigen Microsoft-Dokumentationen immer noch irreführenderweise als "ANSI-Codepage" bezeichnet), die von einer Reihe von Faktoren abhängt. Auf westlichen Systemen ist die Standardcodierung Out-of-the-box Windows Codepage 1252.
Wenn Sie auf Windows UTF-8 in eine Textdatei schreiben, geben Sie möglicherweise encoding="utf-8-sig"
an, das eine BOM-Sequenz am Anfang der Datei hinzufügt. Dies ist streng genommen nicht notwendig oder korrekt, aber einige Windows-Tools benötigen es, um die Codierung korrekt zu erkennen.
Mehrere der früheren Antworten hier schlagen vor, blind eine Codierung anzuwenden, aber hoffentlich hilft Ihnen das zu verstehen, dass dies im Allgemeinen nicht der richtige Ansatz ist, und wie Sie herausfinden - anstatt zu raten - welche Codierung zu verwenden ist.