it-swarm.com.de

Wie überprüfe ich, ob eine Zeichenfolge Unicode oder ASCII ist?

Was muss ich in Python tun, um herauszufinden, welche Codierung ein String hat?

250
TIMEX

In Python 3 sind alle Zeichenfolgen Sequenzen von Unicode-Zeichen. Es gibt einen bytes -Typ, der unformatierte Bytes enthält.

In Python 2 kann ein String vom Typ str oder vom Typ unicode sein. Sie können anhand des folgenden Codes feststellen, welcher Code verwendet wird:

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. Ein Unicode-String kann aus reinen Zeichen im Bereich ASCII bestehen, und ein Bytestring kann ASCII, codierten Unicode oder sogar Nicht-Unicode enthalten -textuelle Daten.

270
Greg Hewgill

Feststellen, ob ein Objekt eine Unicode-Zeichenfolge oder eine Byte-Zeichenfolge ist

Sie können type oder isinstance verwenden.

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 ist str nur eine Folge von Bytes. Python weiß nicht, wie die Kodierung lautet. Die unicode type 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 ist str wie Python 2 ist unicode und wird zum Speichern von Text verwendet genannt str in Python 2 heißt bytes in Python 3.


Feststellen, ob eine Byte-Zeichenfolge gültig ist (UTF-8 oder ASCII)

Sie können decode aufrufen. Wenn es eine UnicodeDecodeError-Ausnahme auslöst, war es 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)
111
Mikel

In python 3.x sind alle Strings Sequenzen von Unicode-Zeichen. Es sollte ausreichen, die isinstance-Prüfung für str (was standardmäßig Unicode-String bedeutet) durchzuführen.

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 überprüfen möchten, ob Sie ein "stringartiges" Objekt mit nur einer Anweisung haben, können Sie Folgendes tun:

isinstance(x, basestring)
43
ThinkBonobo

Unicode ist keine Kodierung - um Kumar McMillan zu zitieren:

Wenn ASCII, UTF-8 und andere Byte-Zeichenfolgen "Text" sind ...

... dann ist Unicode "Text-Ness";

es ist die abstrakte Form des Textes

Lesen Sie McMillans nicode in Python, vollständig entmystifiziert Vortrag von PyCon 2008, in dem die Dinge viel besser erklärt werden als in den meisten verwandten Antworten zu Stack Overflow.

31
Alex Dean

Wenn Ihr Code mit beiden Python 2 und Python 3) kompatibel sein muss, können Sie Dinge wie isinstance(s,bytes) oder isinstance(s,unicode) ohne sie entweder in try/except oder in einen python version test zu verpacken, da bytes undefiniert ist in Python 2 und unicode sind in Python 3 undefiniert.

Es gibt einige hässliche Problemumgehungen. Eine extrem hässliche Methode besteht darin, 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 ist die Überprüfung der Python Versionsnummer, z. B .:

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.

22
Dave Burton

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,
10
madjardi

Beachten Sie, dass es auf Python 3 nicht wirklich fair ist, Folgendes zu sagen:

  • strs sind UTFx für jedes x (zB UTF8)

  • strs sind Unicode

  • strs sind geordnete Sammlungen von Unicode-Zeichen

Der str -Typ von Python ist (normalerweise) eine Folge von Unicode-Codepunkten, von denen einige Zeichen zuordnen.


Selbst auf 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 angewendet.

4
Veedrac

Dies mag jemand anderem helfen. Ich habe mit dem Testen des Stringtyps 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, um was es sich handelt, und kann die Zeichenfolge entsprechend behandeln. Der Code ist nicht makellos, aber ich beabsichtige, dass er Python versionagnostisch ist, ohne einen Versionstest durchzuführen oder sechs zu importieren. Bitte kommentieren Sie den folgenden Beispielcode mit Verbesserungen, um anderen Benutzern 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
2
jfl

Sie können niversal Encoding Detector verwenden. Beachten Sie jedoch, dass dies nur die beste Vermutung liefert und 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 den Content-Type-Header dafür.

2
Seb

Für die py2/py3-Kompatibilität verwenden Sie einfach

import six if isinstance(obj, six.text_type)

0