Die Hauptursache für Probleme bei der Arbeit mit Unicode-Zeichenfolgen ist das Mischen von utf-8-codierten Zeichenfolgen mit Unicode-Zeichenfolgen.
Betrachten Sie beispielsweise die folgenden Skripte.
two.py
# encoding: utf-8
name = 'helló wörld from two'
one.py
# encoding: utf-8
from __future__ import unicode_literals
import two
name = 'helló wörld from one'
print name + two.name
Die Ausgabe von running python one.py
ist:
Traceback (most recent call last):
File "one.py", line 5, in <module>
print name + two.name
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128)
In diesem Beispiel two.name
handelt es sich um eine utf-8-codierte Zeichenfolge (kein Unicode), da sie nicht importiert wurde unicode_literals
, und one.name
um eine Unicode-Zeichenfolge. Wenn Sie beide mischen, versucht Python, die codierte Zeichenfolge zu dekodieren (vorausgesetzt, es handelt sich um ASCII), und konvertiert sie in Unicode. Es würde funktionieren, wenn Sie es tun würden print name + two.name.decode('utf-8')
.
Das gleiche kann passieren, wenn Sie eine Zeichenfolge codieren und später versuchen, sie zu mischen. Zum Beispiel funktioniert dies:
# encoding: utf-8
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
html = html.encode('utf-8')
print 'DEBUG: %s' % html
Ausgabe:
DEBUG: <html><body>helló wörld</body></html>
Aber nach dem Hinzufügen der import unicode_literals
tut es NICHT:
# encoding: utf-8
from __future__ import unicode_literals
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
html = html.encode('utf-8')
print 'DEBUG: %s' % html
Ausgabe:
Traceback (most recent call last):
File "test.py", line 6, in <module>
print 'DEBUG: %s' % html
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 16: ordinal not in range(128)
Es schlägt fehl, weil 'DEBUG: %s'
es sich um eine Unicode-Zeichenfolge handelt und Python daher versucht, sie zu dekodieren html
. Ein paar Möglichkeiten , um den Druck zu beheben sind entweder tun print str('DEBUG: %s') % html
oder print 'DEBUG: %s' % html.decode('utf-8')
.
Ich hoffe, dies hilft Ihnen dabei, die möglichen Fallstricke bei der Verwendung von Unicode-Zeichenfolgen zu verstehen.
decode()
Lösungen anstelle derstr()
oderencode()
-Lösungen zu verwenden: Je häufiger Sie Unicode-Objekte verwenden, desto klarer ist der Code, da Sie Zeichenfolgen und keine Byte-Arrays mit einer extern implizierten Codierung bearbeiten möchten.when you mix utf-8 encoded strings with unicode ones
UTF-8 und Unicode sind nicht zwei verschiedene Codierungen. Unicode ist ein Standard und UTF-8 ist eine der von ihm definierten Codierungen.str
, letzteres ist vom Typunicode
. Da es sich um verschiedene Objekte handelt, kann ein Problem auftreten, wenn Sie versuchen, diese zu summieren / zu verketten / zu interpolierenpython>=2.6
oderpython==2.6
?Auch in 2.6 (vor Python 2.6.5 RC1 +) spielen Unicode-Literale nicht gut mit Schlüsselwortargumenten ( Ausgabe 4978 ):
Der folgende Code funktioniert beispielsweise ohne unicode_literals, schlägt jedoch mit TypeError fehl:
keywords must be string
Wenn unicode_literals verwendet wird.quelle
Ich habe festgestellt, dass Sie, wenn Sie die
unicode_literals
Direktive hinzufügen, auch Folgendes hinzufügen sollten:in die erste oder zweite Zeile Ihrer .py-Datei. Ansonsten Zeilen wie:
führen zu einem Fehler wie:
quelle
# -*- coding: utf-8
ist also eine praktisch obligatorische Aussage, unabhängig davon, ob Sie sie verwendenunicode_literals
oder nicht-*-
ist nicht erforderlich; Wenn Sie sich für den Emacs-kompatiblen Weg entscheiden würden, würden Sie ihn wahrscheinlich brauchen-*- encoding: utf-8 -*-
(siehe auch-*-
am Ende). Alles was Sie brauchen istcoding: utf-8
(oder sogar=
statt:
).from __future__ import unicode_literals
.# -*- coding: utf-8 -*-
"Codierung" (nicht "Codierung" oder "Dateicodierung" oder irgendetwas anderes - Python sucht nur nach "Codierung", unabhängig von einem Präfix).Berücksichtigen Sie auch, dass dies
unicode_literal
Auswirkungen hat,eval()
aber nichtrepr()
(ein asymmetrisches Verhalten, das imho ein Fehler ist), dheval(repr(b'\xa4'))
nicht gleichb'\xa4'
(wie bei Python 3).Im Idealfall ist der folgende Code eine Invariante, die für alle Kombinationen von
unicode_literals
Python {2.7, 3.x} immer funktionieren sollte :Die zweite Behauptung funktioniert zufällig, da
repr('\xa4')
sieu'\xa4'
in Python 2.7 ausgewertet wird .quelle
repr
ein Objekt regenerieren. Aus derrepr
Dokumentation geht eindeutig hervor, dass dies keine Voraussetzung ist. Meiner Meinungrepr
nach bedeutet dies nur etwas Nützliches zum Debuggen.Da sind mehr.
Es gibt Bibliotheken und integrierte Funktionen, die Zeichenfolgen erwarten, die keinen Unicode tolerieren.
Zwei Beispiele:
eingebaut:
(leicht esotisch) funktioniert nicht mit unicode_literals: type () erwartet einen String.
Bibliothek:
funktioniert nicht: Die wx-Pubsub-Bibliothek erwartet einen String-Nachrichtentyp.
Ersteres ist esoterisch und leicht zu reparieren
Letzteres ist jedoch verheerend, wenn Ihr Code voller Aufrufe von pub.sendMessage () ist (was meins ist).
Verdammt, was?!?
quelle
class Meta:
seinb'field_name'
Durch Klicken werden überall Unicode-Ausnahmen ausgelöst, wenn ein Modul dort
from __future__ import unicode_literals
importiert wird, wo Sie es verwendenclick.echo
. Es ist ein Albtraum…quelle