Antworten:
In Python 3 sind alle Zeichenfolgen Sequenzen von Unicode-Zeichen. Es gibt einen bytes
Typ, der Rohbytes enthält.
In Python 2 kann eine Zeichenfolge vom Typ str
oder vom Typ sein unicode
. Mit Code können Sie Folgendes feststellen:
def whatisthis(s):
if isinstance(s, str):
print "ordinary string"
elif isinstance(s, unicode):
print "unicode string"
else:
print "not a string"
Dies unterscheidet nicht zwischen "Unicode oder ASCII". Es werden nur Python-Typen unterschieden. Eine Unicode-Zeichenfolge kann aus reinen Zeichen im ASCII-Bereich bestehen, und ein Bytestring kann ASCII-, codierte Unicode- oder sogar nicht-textuelle Daten enthalten.
Sie können type
oder verwenden isinstance
.
In Python 2:
>>> type(u'abc') # Python 2 unicode string literal
<type 'unicode'>
>>> type('abc') # Python 2 byte string literal
<type 'str'>
In Python 2 str
ist nur eine Folge von Bytes. Python weiß nicht, wie es codiert ist. Der unicode
Typ ist die sicherere Methode zum Speichern von Text. Wenn Sie dies besser verstehen möchten, empfehle ich http://farmdev.com/talks/unicode/ .
In Python 3:
>>> type('abc') # Python 3 unicode string literal
<class 'str'>
>>> type(b'abc') # Python 3 byte string literal
<class 'bytes'>
In Python 3 str
ist es wie in Python 2 unicode
und wird zum Speichern von Text verwendet. Was str
in Python 2 genannt wurde, heißt bytes
in Python 3.
Sie können anrufen decode
. Wenn eine UnicodeDecodeError-Ausnahme ausgelöst wird, war sie nicht gültig.
>>> u_umlaut = b'\xc3\x9c' # UTF-8 representation of the letter 'Ü'
>>> u_umlaut.decode('utf-8')
u'\xdc'
>>> u_umlaut.decode('ascii')
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)
unicode(s, "ascii")
oder so
str(s, "ascii")
In Python 3.x sind alle Zeichenfolgen Sequenzen von Unicode-Zeichen. und die isinstance-Prüfung für str (was standardmäßig Unicode-String bedeutet) sollte ausreichen.
isinstance(x, str)
In Bezug auf Python 2.x scheinen die meisten Leute eine if-Anweisung zu verwenden, die zwei Prüfungen enthält. eine für str und eine für unicode.
Wenn Sie jedoch überprüfen möchten, ob Sie ein 'stringartiges' Objekt mit einer einzigen Anweisung haben, können Sie Folgendes tun:
isinstance(x, basestring)
isinstance(u"x",basestring)
kehrt zurück True
.
Unicode ist keine Kodierung - um Kumar McMillan zu zitieren:
Wenn ASCII, UTF-8 und andere Byte-Zeichenfolgen "Text" sind ...
... dann ist Unicode "Text";
es ist die abstrakte Form von Text
Lesen Sie McMillans Unicode In Python, einem vollständig entmystifizierten Vortrag von PyCon 2008, der die Dinge viel besser erklärt als die meisten verwandten Antworten zu Stack Overflow.
Wenn Ihr Code sowohl mit Python 2 als auch mit Python 3 kompatibel sein muss , können Sie Dinge wie isinstance(s,bytes)
oder isinstance(s,unicode)
ohne Umbruch weder in try / exception noch in einem Python-Versionstest direkt verwenden , da er bytes
in Python 2 unicode
undefiniert und in Python 3 undefiniert ist .
Es gibt einige hässliche Problemumgehungen. Sehr hässlich ist es, den Namen des Typs zu vergleichen , anstatt den Typ selbst zu vergleichen. Hier ist ein Beispiel:
# convert bytes (python 3) or unicode (python 2) to str
if str(type(s)) == "<class 'bytes'>":
# only possible in Python 3
s = s.decode('ascii') # or s = str(s)[2:-1]
elif str(type(s)) == "<type 'unicode'>":
# only possible in Python 2
s = str(s)
Eine wohl etwas weniger hässliche Problemumgehung besteht darin, die Python-Versionsnummer zu überprüfen, z.
if sys.version_info >= (3,0,0):
# for Python 3
if isinstance(s, bytes):
s = s.decode('ascii') # or s = str(s)[2:-1]
else:
# for Python 2
if isinstance(s, unicode):
s = str(s)
Diese sind beide unpythonisch und die meiste Zeit gibt es wahrscheinlich einen besseren Weg.
six
und gegen six.binary_type
undsix.text_type
verwenden:
import six
if isinstance(obj, six.text_type)
Innerhalb der sechs Bibliotheken wird es dargestellt als:
if PY3:
string_types = str,
else:
string_types = basestring,
if isinstance(obj, six.text_type)
. Aber ja das ist imo die richtige Antwort.
Beachten Sie, dass es in Python 3 nicht fair ist, Folgendes zu sagen:
str
s sind UTFx für jedes x (z. B. UTF8)
str
s sind Unicode
str
s sind geordnete Sammlungen von Unicode-Zeichen
Pythons str
Typ ist (normalerweise) eine Folge von Unicode-Codepunkten, von denen einige Zeichen zugeordnet sind.
Selbst unter Python 3 ist es nicht so einfach, diese Frage zu beantworten, wie Sie sich vorstellen können.
Ein offensichtlicher Weg, um auf ASCII-kompatible Zeichenfolgen zu testen, ist ein Codierungsversuch:
"Hello there!".encode("ascii")
#>>> b'Hello there!'
"Hello there... ☃!".encode("ascii")
#>>> Traceback (most recent call last):
#>>> File "", line 4, in <module>
#>>> UnicodeEncodeError: 'ascii' codec can't encode character '\u2603' in position 15: ordinal not in range(128)
Der Fehler unterscheidet die Fälle.
In Python 3 gibt es sogar einige Zeichenfolgen, die ungültige Unicode-Codepunkte enthalten:
"Hello there!".encode("utf8")
#>>> b'Hello there!'
"\udcc3".encode("utf8")
#>>> Traceback (most recent call last):
#>>> File "", line 19, in <module>
#>>> UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in position 0: surrogates not allowed
Die gleiche Methode zur Unterscheidung wird verwendet.
Dies kann jemand anderem helfen. Ich habe mit dem Testen des Zeichenfolgentyps der Variablen s begonnen, aber für meine Anwendung war es sinnvoller, s einfach als utf-8 zurückzugeben. Der Prozess, der return_utf aufruft, weiß dann, womit er es zu tun hat, und kann die Zeichenfolge entsprechend behandeln. Der Code ist nicht makellos, aber ich beabsichtige, dass er Python-Versionsunabhängig ist, ohne dass ein Versionstest durchgeführt oder sechs importiert werden. Bitte kommentieren Sie den folgenden Beispielcode mit Verbesserungen, um anderen Personen zu helfen.
def return_utf(s):
if isinstance(s, str):
return s.encode('utf-8')
if isinstance(s, (int, float, complex)):
return str(s).encode('utf-8')
try:
return s.encode('utf-8')
except TypeError:
try:
return str(s).encode('utf-8')
except AttributeError:
return s
except AttributeError:
return s
return s # assume it was already utf-8
Sie könnten den Universal Encoding Detector verwenden , aber beachten Sie, dass er Ihnen nur die bestmögliche Vermutung gibt, nicht die tatsächliche Codierung, da es beispielsweise unmöglich ist, die Codierung eines Strings "abc" zu kennen. Sie müssen Codierungsinformationen an anderer Stelle abrufen, z. B. verwendet das HTTP-Protokoll dafür den Content-Type-Header.
Für py2 / py3-Kompatibilität einfach verwenden
import six
if isinstance(obj, six.text_type)
Ein einfacher Ansatz besteht darin, zu überprüfen, ob unicode
es sich um eine integrierte Funktion handelt. Wenn ja, befinden Sie sich in Python 2 und Ihre Zeichenfolge ist eine Zeichenfolge. Um sicherzustellen, dass alles in unicode
einem ist, kann man:
import builtins
i = 'cats'
if 'unicode' in dir(builtins): # True in python 2, False in 3
i = unicode(i)