Beste Antwort
Leider gibt es keine einfache einzeilige Antwort auf dieses Problem.
Stellen Sie sich vor, eine Zeichenfolge gelangt über eine E / A-Operation (vom Terminal, aus der Datei oder aus dem Netzwerk gelesen) in ein Python-Programm. Sie umgeht das Programm und wird von Ort zu Ort kopiert. und schließlich wird es über eine E / A-Operation ausgegeben. Wenn Sie einem Str einen Unicode zuweisen, wird in jedem Schritt der gefürchtete Fehler ascii codec can"t encode...
angezeigt. Leider gibt es keinen einfachen Weg, ihn zu beheben, außer zu gehen durch Ihren Code, der alle Stellen repariert.
Betrachten Sie zum Beispiel:
f\_in = open("filein.txt")
line = f\_in.read()
out\_msg = "The input line was: {line}".format(line=line)
f\_out = open("fileout.txt")
Wenn Sie nicht wissen, welche Codierung beim Speichern von filein.txt verwendet wurde, treten bizarre Verhaltensweisen auf, und einige Zeichen in Ihrer line
sehen wie Müll aus. (Hinweis: Sie haben gewonnen. “ Sie erhalten nicht den Fehler ascii codec can"t encode...
, aber die Ergebnisse sind trotzdem schlecht.) Sie müssen also Folgendes verwenden: f\_in = codecs.open("filein.txt", "rb", "utf-8")
und dann verzweifelt hoffen derjenige, der filein.txt gespeichert hat, hat es in utf-8 und nicht in einer der anderen UTF-Codierungen gespeichert. (Hinweis: utf-8 ist abwärtskompatibel mit ASCII, sodass eine Datei, die mit regulärem ASCII gespeichert wurde, mit Utf-8-Codierung problemlos geöffnet werden kann.)
Inzwischen haben Sie dies offensichtlich erkannt, es sei denn, Sie Öffnen Sie die Datei fileout.txt mit einer geeigneten Unicode-Codierung. Sie werden erneut auf Probleme stoßen und den Fehler ascii codec can"t encode...
erhalten (wenn Ihre out\_msg ein Unicode-Zeichen enthält). Sie müssen also codecs.open("fileout.txt", "wb", "utf-8")
(Hinweis: Die Verwendung einer utf-8-Codierung zum Speichern von regulären ASCII ist kein Problem, da sie aufwärtskompatibel ist. Wenn Ihr Text also keine Nicht-ASCII-Unicode-Zeichen enthält Die utf-8-codierte Datei ist identisch mit einer normalen ASCII-Datei.)
Was mich aus der Fassung gebracht hat, war, dass diese beiden Dinge nicht gut genug sind. Betrachten Sie diesen aktualisierten Code:
f\_in = codecs.open("filein.txt", "rb", "utf-8")
line = f\_in.read()
out\_msg = "The input line was: {line}".format(line=line)
f\_out = codecs.open("fileout.txt", "wb", "utf-8")
Dies könnte beim dritten immer noch den gleichen gefürchteten Fehler verursachen Linie. Das ist richtig, das Problem ist, dass "The input line was: {line}".format(xxx)"
eine str
ist und wenn line
enthält Alle Unicode-Zeichen (womit ich Zeichen meine, die nicht in ASCII codiert werden können) sind in Schwierigkeiten.
Die Lösung hierfür lautet:
out\_msg = u"The input line was: {line}".format(line=line)
(Ja, diese Zeile unterscheidet sich von Zeile 3 im Codebeispiel. Sie müssen nur genau hinschauen.)
Da haben Sie es also. Sie müssen es durchgehen Suchen Sie in jeder Zeile Ihres Codes nach Stellen, an denen Unicode str zugewiesen wird (oder an eine Methode gesendet wird, die eine str erwartet), und legen Sie fest, dass das Ziel Unicode anstelle von str ist.
Um Unicode in zu verstehen Python besser, werfen Sie einen Blick auf: http://farmdev.com/thoughts/23/what-i-thought-i-knew-about-unicode-in-python-amounted-to-nothing/
Um Unicode im Allgemeinen zu verstehen (und ich würde hoch empfehle, dass Sie dies tun sollten) Lesen Sie Joel Spolskys „Das absolute Minimum“, das jeder Softwareentwickler unbedingt über Unicode und Zeichensätze wissen muss (Nr Ausreden!) „: http://www.joelonsoftware.com/articles/Unicode.html
Und während Sie darüber nachdenken, können Sie auch lesen: Was ist die beste Quelle, um mehr über Best Practices für Unicode zu erfahren in Python?
Quick „n Dirty Hack: Wenn Sie nur eine Ausgabe in ungefährem ASCII drucken möchten, können Sie Folgendes tun:
import unicodedata
line = unicodedata.normalize("NFKD", line).encode("ascii","ignore")
Dies ersetzt alle Nicht-ASCII-Zeichen durch das nächstgelegene ASCII-Äquivalent oder ignoriert das Zeichen einfach, wenn nichts angemessen ist . Ist für viele Zwecke gut genug …
Antwort
Sie sollten Ihre Unicode-Zeichenfolgen (die aus Zeichen bestehen, einer von der Speichergröße entkoppelten Einheit) mit der richtigen Codierung in Bytes konvertieren Bevor Sie eine E / A damit ausführen.
Standardmäßig versucht Python, Ihre Unicode-Zeichenfolge beim Schreiben in stdout mithilfe der ASCII-Codierung zu codieren (dh mit print ), aber diese Codierung kann „nicht jedes Unicode-Zeichen darstellen, weshalb der folgende Fehler angezeigt wird:“ „ascii“ -Codec kann „Zeichen nicht codieren“. Ziemlich explizit.
Sie sollten eine geeignete Codierung auswählen und Ihre Unicode-Zeichenfolge damit codieren. Beispielsweise ist UTF-8 eine effiziente Codierung, die jedes Unicode-Zeichen verarbeiten kann. Angenommen, foo ist eine Unicode-Zeichenfolge, könnten (und sollten) Sie Folgendes tun: print foo.encode („utf -8 „) statt nur print foo . Stellen Sie einfach sicher, dass Ihr Terminal oder was auch immer die von Ihnen ausgewählte Codierung versteht.Nochmals: UTF-8 ist die heißeste Codierung für solche Szenarien. Sie möchten sie wahrscheinlich verwenden, es sei denn, Sie haben ganz bestimmte Anforderungen.