Warum Unicode () verwendet str () auf meinem Objekt nur mit keiner Codierung gegeben?

StackOverflow https://stackoverflow.com/questions/106630

  •  01-07-2019
  •  | 
  •  

Frage

Ich beginne mit einem String-Variable mit einigen Nicht-ascii Erstellen utf-8 codierte Daten über sie:

>>> text = 'á'
>>> text
'\xc3\xa1'
>>> text.decode('utf-8')
u'\xe1'

Mit unicode() auf sie Fehler wirft ...

>>> unicode(text)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: 
                    ordinal not in range(128)

... aber wenn ich die Codierung weiß, ich kann es als zweiten Parameter verwenden:

>>> unicode(text, 'utf-8')
u'\xe1'
>>> unicode(text, 'utf-8') == text.decode('utf-8')
True

Nun, wenn ich eine Klasse, die diesen Text in der __str__() Methode gibt:

>>> class ReturnsEncoded(object):
...     def __str__(self):
...         return text
... 
>>> r = ReturnsEncoded()
>>> str(r)
'\xc3\xa1'

unicode(r) scheint str() auf, es zu benutzen, da sie die gleichen Fehler wie unicode(text) oben aufwirft:

>>> unicode(r)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: 
                    ordinal not in range(128)

Bis jetzt ist alles wie geplant!

Aber wie würde niemand jemals erwarten, unicode(r, 'utf-8') nicht einmal versuchen:

>>> unicode(r, 'utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: coercing to Unicode: need string or buffer, ReturnsEncoded found

Warum? Warum dies inkonsistentes Verhalten? Ist es ein Fehler? ist beabsichtigt? Sehr umständlich.

War es hilfreich?

Lösung

Das Verhalten scheint verwirrend, aber intensionalen. Ich gebe hier die Gesamtheit der Unicode-Dokumentation aus dem Python Integrierte Funktionen Dokumentation (für Version 2.5.2, da ich dies schreibe):

  

Unicode ([object [, Kodierung [Fehler]]])

     

Gibt die Unicode-String-Version des Objekts eine der folgenden Modi:

     

Wenn Codierung und / oder Fehler gegeben, Unicode () dekodiert die      Gegenstand, der entweder ein 8-Bit-String oder ein Zeichenpuffer sein kann,      Verwendung der Codec für die Codierung. Die Kodierungsparameter ist ein String      geben den Namen eines Codiersystems; wenn die Kodierung nicht bekannt ist,      LookupError angehoben. Die Fehlerbehandlung wird nach getan      Fehler; Dies gibt die Behandlung von Zeichen, die      invalid im Eingangscodierung. Wenn Fehler ist ‚strenge‘ (das      Standard), wird ein Valueerror auf Fehler angehoben, während ein Wert von      ‚Ignore‘ verursacht Fehler stillschweigend ignoriert werden, und ein Wert von      ‚Ersetzen‘ bewirkt, dass die offiziellen Unicode-Ersatzzeichen,      U + FFFD, werden verwendet, um Eingangszeichen zu ersetzen, die nicht sein kann      decodiert. Siehe auch die Codecs Modul.

     

Wenn keine optionalen Parameter angegeben werden, Unicode () wird imitieren die      Verhalten von str (), außer dass es gibt Unicode-Strings      anstelle von 8-Bit-Strings. Genauer gesagt, wenn das Objekt eine Unicode ist      String oder Unterklasse wird es, dass Unicode-String zurück, ohne      Jede zusätzliche Decodierung angewendet.

     

Für Objekte, die einen __unicode __ () -Methode zur Verfügung stellen, wird es nennen      diese Methode ohne Argumente eine Unicode-Zeichenfolge zu erstellen. Zum      alle anderen Objekte, die 8-Bit-String-Version oder Darstellung      angefordert und dann in einen Unicode-String konvertiert den Codec      für die Standard-Kodierung in ‚strenge‘ Modus.

     

Neu in der Version 2.0. Geändert in Version 2.2: Unterstützung für __unicode __ () hinzugefügt.

Wenn Sie also unicode(r, 'utf-8') nennen, erfordert es einen 8-Bit-String oder einen Zeichenpuffer als erstes Argument, so dass es nötigt Ihr Objekt der __str__() Methode verwendet, und versucht zu entschlüsseln, dass die utf-8 Codec. Ohne den utf-8 sieht die unicode() Funktion für ein für eine __unicode__() Methode auf dem Objekt, und findet es nicht, ruft die __str__() Methode, wie Sie vorgeschlagen, zu versuchen, die Standard-Codec zu verwenden, um Unicode zu konvertieren.

Andere Tipps

unicode erraten nicht die Codierung Ihres Textes. Wenn Ihr Objekt selbst als unicode drucken können, definieren die __unicode__() Methode, die eine Unicode-Zeichenfolge zurückgibt.


Das Geheimnis ist, dass unicode(r) nicht tatsächlich __str__() selbst aufrufen. Stattdessen sieht es für eine __unicode__() Methode. Die Standardimplementierung von __unicode__() wird __str__() aufrufen und dann sie zu entschlüsseln versuchen, die ascii charset verwenden. Wenn Sie die Codierung übergeben, erwartet unicode() das erste Objekt etwas sein, das decodiert werden kann -. Das heißt, eine Instanz von basestring


  

Das Verhalten ist seltsam, weil es versucht, als ascii zu dekodieren, wenn ich nicht passieren ‚utf-8‘. Aber wenn ich 'utf-8' Pass gibt es einen anderen Fehler ...

Das ist, weil, wenn Sie „utf-8“ angeben, ist es den ersten Parameter behandelt, als ein strangartige Objekt decodiert werden. Ohne sie, es behandelt die Parameter als ein Objekt zu Unicode gezwungen werden.

Ich verstehe nicht, die Verwirrung. Wenn Sie wissen, dass das text Attribut des Objekts wird immer UTF-8 kodiert sein, nur __unicode__() definieren und dann wird alles gut funktionieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top