Réponses:
En Python 3, toutes les chaînes sont des séquences de caractères Unicode. Il existe un bytestype qui contient des octets bruts.
En Python 2, une chaîne peut être de type strou de type unicode. Vous pouvez dire quel code quelque chose comme ceci:
def whatisthis(s):
if isinstance(s, str):
print "ordinary string"
elif isinstance(s, unicode):
print "unicode string"
else:
print "not a string"
Cela ne distingue pas "Unicode ou ASCII"; il distingue uniquement les types Python. Une chaîne Unicode peut être constituée uniquement de caractères dans la plage ASCII, et un sous-test peut contenir des données ASCII, Unicode codées ou même des données non textuelles.
Vous pouvez utiliser typeou isinstance.
En Python 2:
>>> type(u'abc') # Python 2 unicode string literal
<type 'unicode'>
>>> type('abc') # Python 2 byte string literal
<type 'str'>
En Python 2, strc'est juste une séquence d'octets. Python ne sait pas quel est son encodage. Le unicodetype est le moyen le plus sûr de stocker du texte. Si vous voulez mieux comprendre cela, je recommande http://farmdev.com/talks/unicode/ .
En Python 3:
>>> type('abc') # Python 3 unicode string literal
<class 'str'>
>>> type(b'abc') # Python 3 byte string literal
<class 'bytes'>
En Python 3, strc'est comme Python 2 unicodeet est utilisé pour stocker du texte. Ce qui était appelé stren Python 2 est appelé bytesen Python 3.
Vous pouvez appeler decode. S'il déclenche une exception UnicodeDecodeError, il n'est pas valide.
>>> 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")ou quelque chose
str(s, "ascii")
En python 3.x, toutes les chaînes sont des séquences de caractères Unicode. et faire la vérification isinstance de str (ce qui signifie une chaîne unicode par défaut) devrait suffire.
isinstance(x, str)
En ce qui concerne python 2.x, la plupart des gens semblent utiliser une instruction if qui comporte deux vérifications. un pour str et un pour unicode.
Si vous souhaitez vérifier si vous avez un objet "semblable à une chaîne" avec une seule instruction, vous pouvez effectuer les opérations suivantes:
isinstance(x, basestring)
isinstance(u"x",basestring)revient True.
Unicode n'est pas un encodage - pour citer Kumar McMillan:
Si ASCII, UTF-8 et les autres chaînes d'octets sont du "texte" ...
... alors Unicode est "text-ness";
c'est la forme abstraite du texte
Lisez Unicode In Python de McMillan , un discours complètement démystifié de PyCon 2008, il explique les choses beaucoup mieux que la plupart des réponses connexes sur Stack Overflow.
Si vos besoins de code pour être compatibles avec les deux Python 2 et Python 3, vous ne pouvez pas utiliser directement des choses comme isinstance(s,bytes)ou isinstance(s,unicode)sans les envelopper dans les deux try / except ou un test de la version python, parce que bytesn'est pas défini en Python 2 et unicodeest indéfini en Python 3 .
Il existe des solutions de contournement laides. Un très laid est de comparer le nom du type, au lieu de comparer le type lui-même. Voici un exemple:
# 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)
Une solution de contournement sans doute un peu moins laide consiste à vérifier le numéro de version de Python, par exemple:
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)
Ce sont tous deux impythoniques, et la plupart du temps, il y a probablement une meilleure façon.
sixet de tester contre six.binary_typeetsix.text_type
utilisation:
import six
if isinstance(obj, six.text_type)
à l'intérieur de la bibliothèque six, il est représenté comme:
if PY3:
string_types = str,
else:
string_types = basestring,
if isinstance(obj, six.text_type) . Mais oui, c'est la bonne réponse.
Notez que sur Python 3, il n'est pas vraiment juste de dire:
strs sont UTFx pour tout x (par exemple UTF8)
strs sont Unicode
strs sont des collections ordonnées de caractères Unicode
Le strtype de Python est (normalement) une séquence de points de code Unicode, dont certains sont mappés sur des caractères.
Même sur Python 3, il n'est pas aussi simple de répondre à cette question que vous pourriez l'imaginer.
Une façon évidente de tester les chaînes compatibles ASCII est par une tentative de codage:
"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)
L'erreur distingue les cas.
En Python 3, certaines chaînes contiennent même des points de code Unicode non valides:
"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
La même méthode pour les distinguer est utilisée.
Cela peut aider quelqu'un d'autre, j'ai commencé à tester le type de chaîne de la variable s, mais pour mon application, il était plus logique de renvoyer simplement s comme utf-8. Le processus appelant return_utf sait alors de quoi il s'agit et peut gérer la chaîne de manière appropriée. Le code n'est pas vierge, mais j'ai l'intention qu'il soit agnostique en version Python sans test de version ni importation de six. Veuillez commenter les améliorations apportées à l'exemple de code ci-dessous pour aider d'autres personnes.
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
Vous pouvez utiliser Universal Encoding Detector , mais sachez qu'il ne vous donnera que la meilleure estimation, pas l'encodage réel, car il est impossible de connaître l'encodage d'une chaîne "abc" par exemple. Vous devrez obtenir des informations d'encodage ailleurs, par exemple, le protocole HTTP utilise l'en-tête Content-Type pour cela.
Pour la compatibilité py2 / py3, utilisez simplement
import six
if isinstance(obj, six.text_type)
Une approche simple consiste à vérifier s'il unicodes'agit d'une fonction intégrée. Si c'est le cas, vous êtes en Python 2 et votre chaîne sera une chaîne. Pour vous assurer que tout est en unicodeun, vous pouvez:
import builtins
i = 'cats'
if 'unicode' in dir(builtins): # True in python 2, False in 3
i = unicode(i)