Comment vérifier si une chaîne en Python est en ASCII?

je veux vérifier si une chaîne est en ASCII ou non.

je suis au courant de ord() , cependant quand j'essaie ord('é') , j'ai TypeError: ord() expected a character, but string of length 2 found . J'ai compris que c'est provoqué par la manière dont j'ai construit Python (comme expliqué dans ord() documentation ).

y a-t-il un autre moyen de vérifier?

166
demandé sur Amir 2008-10-13 04:13:40

16 réponses

def is_ascii(s):
    return all(ord(c) < 128 for c in s)
135
répondu Alexander Kojevnikov 2008-10-13 00:30:43

je pense que vous n'êtes pas poser la bonne question--

une chaîne en python n'a aucune propriété correspondant à 'ascii', utf-8, ou tout autre encodage. La source de votre chaîne (si vous le lisez à partir d'un fichier d'entrée à partir d'un clavier, etc.) peut avoir codé une chaîne unicode en ascii pour produire votre chaîne, mais c'est là que vous devez aller pour une réponse.

peut-être que la question que vous pouvez poser est: "Est-ce que cette chaîne est le résultat de l'encodage d'une unicode une ficelle en ascii?"-- Ceci vous pouvez répondre en essayant:

try:
    mystring.decode('ascii')
except UnicodeDecodeError:
    print "it was not a ascii-encoded unicode string"
else:
    print "It may have been an ascii-encoded unicode string"
225
répondu Vincent Marchetti 2008-10-13 00:30:32

Python 3:

isascii = lambda s: len(s) == len(s.encode())
120
répondu far 2016-01-19 13:05:58

est tombé sur quelque chose comme ça récemment - pour référence future

import chardet

encoding = chardet.detect(string)
if encoding['encoding'] == 'ascii':
    print 'string is in ascii'

que vous pouvez utiliser avec:

string_ascii = string.decode(encoding['encoding']).encode('ascii')
18
répondu Alvin 2011-08-08 20:47:22

votre question est incorrecte; l'erreur que vous voyez n'est pas le résultat de la façon dont vous avez construit python, mais d'une confusion entre les chaînes byte et unicode.

Les chaînes D'octets

(par exemple "foo", ou "bar", en syntaxe python) sont des séquences d'octets; nombres de 0 à 255. Les chaînes Unicode (par exemple u"foo" ou u'Bar') sont des séquences de points de code unicode; nombres de 0-1112064. Mais vous semblez être intéressé par le caractère é, qui (dans votre terminal) est une séquence de plusieurs octets que représente un seul caractère.

au lieu de ord(u'é') , essayez ceci:

>>> [ord(x) for x in u'é']

qui vous indique quelle séquence de points de code" é " représente. Il peut vous donner [233], ou il peut vous donner [101, 770].

au lieu de chr() pour inverser cela, il y a unichr() :

>>> unichr(233)
u'\xe9'

ce caractère peut en fait être représenté par un ou plusieurs points de code unicode "", qui représentent eux-mêmes soit des graphèmes, soit des caractères. C'est soit" e avec un accent aigu (i.e., code point 233)", soit" e "(code point 101), suivi de" un accent aigu sur le caractère précédent " (code point 770). Donc ce même caractère peut être présenté comme la structure de données Python u'e\u0301' ou u'\u00e9' .

la plupart du temps, vous ne devriez pas avoir à vous soucier de cela, mais il peut devenir un problème si vous itérez sur une chaîne unicode, comme itération fonctionne par point de code, pas par caractère décomposable. En d'autres termes, len(u'e\u0301') == 2 et len(u'\u00e9') == 1 . Si cela vous importe, vous pouvez convertir entre les formes composées et décomposées en utilisant unicodedata.normalize .

le glossaire Unicode peut être un guide utile pour comprendre certaines de ces questions, en soulignant comment chaque terme spécifique se réfère à une partie différente de la représentation du texte, ce qui est beaucoup plus compliqué que beaucoup de programmeurs se rendent compte.

17
répondu Glyph 2011-07-08 02:10:02

pourquoi ne pas faire ça?

import string

def isAscii(s):
    for c in s:
        if c not in string.ascii_letters:
            return False
    return True
10
répondu miya 2008-10-13 16:38:25

Vincent Marchetti a la bonne idée, mais str.decode a été déprécié en Python 3. En Python 3, vous pouvez faire le même test avec str.encode :

try:
    mystring.encode('ascii')
except UnicodeEncodeError:
    pass  # string is not ascii
else:
    pass  # string is ascii

Note l'exception que vous voulez attraper a aussi changé de UnicodeDecodeError à UnicodeEncodeError .

9
répondu drs 2015-09-02 15:45:04

j'ai trouvé cette question en essayant de déterminer comment utiliser/encoder/décoder une chaîne dont je n'étais pas sûr de l'encodage (et comment échapper/convertir des caractères spéciaux dans cette chaîne).

ma première étape aurait dû être de vérifier le type de la chaîne - je n'ai pas réalisé là que je pouvais obtenir de bonnes données sur son formatage à partir de type(s). Cette réponse a été très utile et a obtenu à l'origine de mes problèmes.

si vous obtenez un impoli et persistante

UnicodeDecodeError: 'ascii' codec ne peut pas décoder les octets 0xc3 en position 263: ordinal pas in range(128)

surtout quand vous encodez, assurez - vous de ne pas essayer unicode() une chaîne qui est déjà unicode-pour une raison terrible, vous obtenez des erreurs ASCII codec. (Voir aussi la Python Kitchen recipe , et les Python docs tutoriels for mieux comprendre à quel point cela peut être terrible.)

finalement j'ai déterminé que ce que je voulais faire était ceci:

escaped_string = unicode(original_string.encode('ascii','xmlcharrefreplace'))

aussi utile dans le débogage était de définir le codage par défaut dans mon fichier à utf-8 (mettez ceci au début de votre fichier python):

# -*- coding: utf-8 -*-

qui vous permet de tester des caractères spéciaux ('àéç') sans avoir à utiliser leurs échappées unicode (u'\xe0\xe9\xe7').

>>> specials='àéç'
>>> specials.decode('latin-1').encode('ascii','xmlcharrefreplace')
'&#224;&#233;&#231;'
8
répondu Max P Magee 2017-05-23 11:55:10

pour améliorer la solution D'Alexander à partir du python 2.6 (et en Python 3.x) vous pouvez utiliser les malédictions du module helper.les ascii et les malédictions.ASCII.fonction isascii () ou autre: https://docs.python.org/2.6/library/curses.ascii.html

from curses import ascii

def isascii(s):
    return all(ascii.isascii(c) for c in s)
4
répondu Sergey Nevmerzhitsky 2015-05-22 09:17:16

vous pouvez utiliser la bibliothèque d'expressions régulières qui accepte la définition du standard Posix [[:ASCII:]].

2
répondu Steve Moyer 2008-10-13 00:18:25

un sting ( str - type) en Python est une série d'octets. Il y a impossible de dire simplement en regardant la chaîne si cette série d'octets représente une chaîne ascii, une chaîne dans un jeu de caractères 8 bits comme ISO-8859-1 ou une chaîne encodée avec UTF-8 ou UTF-16 ou n'importe quoi d'autre.

cependant si vous connaissez l'encodage utilisé, alors vous pouvez decode le str dans une chaîne unicode et ensuite utiliser une expression régulière (ou une boucle) pour vérifier si elle contient des caractères en dehors de la plage qui vous concerne.

2
répondu JacquesB 2008-10-14 08:10:06

nouveau en Python 3.7 ( bpo32677 )

plus de contrôles ASCII fatigants/inefficaces sur les chaînes, nouveau intégré str / bytes / bytearray méthode - .isascii() vérifiera si les chaînes sont ascii.

print("is this ascii?".isascii())
# True
2
répondu abccd 2018-07-02 18:32:22

pour empêcher votre code de s'écraser, vous pouvez utiliser un try-except pour attraper TypeErrors

>>> ord("¶")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: ord() expected a character, but string of length 2 found

par exemple

def is_ascii(s):
    try:
        return all(ord(c) < 128 for c in s)
    except TypeError:
        return False
0
répondu Sebastian 2013-07-07 21:16:00
import re

def is_ascii(s):
    return bool(re.match(r'[\x00-\x7F]+$', s))

pour inclure une chaîne vide comme ASCII, remplacer le + par * .

0
répondu Roger Dahl 2015-09-30 14:51:52

comme de @RogerDahl "réponse mais il est plus efficace de court-circuit en annulant la classe de caractères et en utilisant la recherche au lieu de find_all ou match .

>>> import re
>>> re.search('[^\x00-\x7F]', 'Did you catch that \x00?') is not None
False
>>> re.search('[^\x00-\x7F]', 'Did you catch that \xFF?') is not None
True

j'imagine qu'une expression régulière est bien optimisée pour cela.

0
répondu hobs 2017-05-23 12:18:24

j'utilise ce qui suit pour déterminer si la chaîne est ascii ou unicode:

>> print 'test string'.__class__.__name__
str
>>> print u'test string'.__class__.__name__
unicode
>>> 

, Alors il suffit d'utiliser un bloc conditionnel pour définir la fonction:

def is_ascii(input):
    if input.__class__.__name__ == "str":
        return True
    return False
-4
répondu user397587 2010-07-21 06:34:56