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.
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. –