2009-10-06 7 views
5

I erhalten Codierungsfehler auf dieser Linie:Warum bekomme ich Kodierung Fehler in Python warnings.formatwarning auf Formatzeichenfolge?

s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message) 

UnicodeEncodeError: 'ASCII' Codec nicht Charakter kodieren, können u '\ XC4' in Position 44: ordinal nicht im Bereich (128)

ich versuchte um diesen Fehler zu reproduzieren, indem man alle Kombinationen von Parametern an das String-Format übergibt, aber am nächsten kam "ascii decode" -Fehler (durch gleichzeitiges Übergeben von Unicode und high ASCII-String, was die Umwandlung von String in Unicode unter Verwendung eines ASCII-Decoders erforderlich machte) Jedoch habe ich es nicht geschafft, "Ascii encode" Fehler zu bekommen. Jeder hat eine Idee?

+1

Oh, Sie bekommen es, wenn warnings.warn aufgerufen wird ... Konnten Sie das nicht gesagt haben? Es war unklar, dass der Code nicht Ihr Code war, sondern in der Standardbibliothek. Sie sollten sagen, was Ihr Problem ist, nicht eine generische Frage, von der Sie denken, dass sie das Problem ist, weil dies im Allgemeinen nicht der Fall ist. Ich habe meine Antwort unten mit weiteren Details aktualisiert. –

Antwort

8

Dies geschieht, wenn Python versucht, ein Argument zu zwingen:

s = u"\u00fc" 
print str(s) 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 0: ordinal not in range(128) 

Dies geschieht, weil eines Ihrer Argumente ein Objekt ist (kein String jeglicher Art) und Python ruft str() darauf. Es gibt zwei Lösungen: Verwenden Sie eine Unicode-Zeichenfolge für das Format (s = u"%s...") oder wickeln Sie jedes Argument mit repr().

+1

Das Format ist im Warnungsmodul, also würde ich es lieber nicht ändern, aber das Hinzufügen von repr() um übergebene Parameter klingt wirklich gut. Vielen Dank! –

+0

Dann erhalten Sie zusätzliche Angebote und eine zusätzliche u. Funktioniert als Hack, aber nicht sehr hübsch. –

+1

Fehler tritt auf, wenn die von der Datenbank ausgelöste Warnung für eine Protokollierung erfasst wird. Als das Protokollieren fehlschlug, bin ich völlig im Dunkeln über das ursprüngliche Problem, welches der schlimmste Ort ist. Ich mag meine Protokolle lesbar als die nächste Person, also habe ich beschlossen, die Formatierung in einem Versuch zu wickeln: außer: Block, zuerst "schön", und mit repl() nur im Falle von Codierungsfehler, einschließlich zusätzlicher Warnung zu werfen über das Codierproblem. IMHO, das ist kein Hack, es ist besser, sicherer, Protokollierung. –

1

Einer der Operanden, die Sie übergeben, ist nicht für die ASCII-Codierung geeignet - möglicherweise enthält er entweder Unicode- oder Latin-1-Zeichen. Ändern Sie die Formatzeichenfolge in Unicode und sehen Sie, was passiert.

+0

Dies sollte einen _decode_ Fehler erzeugen, d. H. s = "% s% s"% (unichr (2000), chr (200)) Der Fehler hier scheint etwas anderes zu sein. –

+0

@cortex: Manchmal entscheidet sich Python, nicht zu Unicode zu zwingen, sondern zu String zu zwingen. Ich bin mir nicht sicher, wie genau diese Entscheidung getroffen wird. –

8

Sie mischen Unicode- und Str-Objekte.

Erläuterung: In Python 2.x gibt es zwei Arten von Objekten, die Textzeichenfolgen enthalten können. str und Unicode. str ist eine Zeichenfolge aus Bytes, daher kann sie nur Zeichen zwischen 0 und 255 enthalten. Unicode ist eine Zeichenfolge aus Unicode-Zeichen.

>>> "thisisastring".decode('ascii') 
u'thisisastring' 

>>> u"This is ä string".encode('utf8')  
'This is \xc3\xa4 string' 

Beachten Sie die Codierungen:

Sie können zwischen str und Unicode mit dem "codieren" und "decode" Methoden konvertieren. Kodierungen sind Möglichkeiten, Unicode-Text als nur Byte-Bytes darzustellen.

Wenn Sie versuchen, str und Unicode zusammenzufügen, wird Python versuchen, eines in das andere zu konvertieren. Aber standardmäßig wird ASCII als Codierung verwendet, dh a-z, A-Z und einige zusätzliche Zeichen wie !"#$%&/()=?'{[]]} usw. Alles andere wird fehlschlagen.

Sie werden an diesem Punkt entweder einen Kodierungsfehler oder einen Dekodierungsfehler erhalten, abhängig davon, ob Python versucht, den Unicode in str oder str in Unicode zu konvertieren. Normalerweise versucht es zu dekodieren, das heißt in Unicode zu konvertieren. Aber manchmal beschließt es, nicht zu zwingen, zu stringeln. Ich bin mir nicht ganz sicher warum.

Update: Der Grund, warum Sie einen kodieren Fehler bekommen und nicht über einen Decodierfehler ist, dass message in dem obigen Code weder str noch Unicode ist. Es ist ein anderes Objekt, das eine str Methode hat. Daher gibt Python str (message) aus, bevor es übergeben wird, und das schlägt fehl, da die intern gespeicherte Nachricht ein Unicode-Objekt ist, das nicht in ascii umgewandelt werden kann.

Oder einfacher beantwortet: Es schlägt fehl, da warnings.warn() Unicode-Nachrichten nicht akzeptiert.

nun die Lösung:

Sie str und Unicode nicht mischen. Wenn du Unicode verwenden musst, und du es anscheinend tust, versuche sicherzustellen, dass alle Strings immer Unicode sind. Nur so können Sie sicher sein, dass Sie dies vermeiden. Dies bedeutet, dass Sie jedes Mal, wenn Sie eine Zeichenfolge von der Festplatte eingelesen haben, oder einen Aufruf an eine Funktion, die etwas anderes als pure ascii str zurückgeben kann, so schnell wie möglich in Unicode dekodieren. Und wenn Sie es auf Festplatte speichern oder über ein Netzwerk senden oder es an eine Methode übergeben müssen, die Unicode nicht versteht, codieren Sie es so spät wie möglich.

In diesem speziellen Fall besteht das Problem darin, dass Sie Unicode an warnings.warn() übergeben, und Sie können das nicht tun. Übergeben Sie eine Zeichenfolge. Wenn Sie nicht wissen, was es ist (wie es hier der Fall zu sein scheint), weil es von woanders kommt, funktioniert Ihre try/except-Lösungen mit einem Ausdruck gut, obwohl eine Kodierung eine Möglichkeit wäre.

+2

Ich denke, der Fragesteller ist sich der Tatsache bewusst, dass das Problem ist, dass Unicode und Str irgendwie gemischt sind; Die Frage ist, warum dieser Fehler bei einer Operation ausgelöst wird, die normalerweise die Ausgabe auf Unicode erzwingen soll. –

+1

Möglich, aber ich ging für eine erschöpfende Antwort. Und das Problem ist immer noch das Mischen von Unicode und Str. Warum es in diesem speziellen Fall einen Fehler anstelle des anderen gibt, weiß ich nicht, ich kann es nicht reproduzieren. Aber ich habe es selbst erlebt. –

+1

So können Sie es reproduzieren: 'Warnungen importieren; warnings.warn (u'Предупреждение) ' –

Verwandte Themen