Question

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

Je suis au courant de ord () , mais lorsque j'essaie ord ('& # 233;') , j'ai TypeError: ord () attendu un caractère, mais une chaîne de longueur 2 trouvée . J'ai compris que c'était dû à la façon dont j'avais construit Python (comme expliqué dans ord () la documentation de ).

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

Était-ce utile?

La solution

def is_ascii(s):
    return all(ord(c) < 128 for c in s)

Autres conseils

Je pense que vous ne posez pas la bonne question -

Une chaîne en python ne possède pas de propriété correspondant à 'ascii', utf-8, ni à aucun autre encodage. La source de votre chaîne (que vous lisiez un fichier, une entrée au clavier, etc.) a peut-être encodé une chaîne unicode en ascii pour produire votre chaîne, mais c'est là que vous devez rechercher une réponse.

La question que vous pouvez vous poser est peut-être: "Cette chaîne est-elle le résultat du codage d'une chaîne unicode en ascii?" - Ceci tu peux 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"

Python 3 way:

isascii = lambda s: len(s) == len(s.encode())

Pour vérifier, transmettez la chaîne de test:

str1 = "♥O◘♦♥O◘♦"
str2 = "Python"

print(isascii(str1)) -> will return False
print(isascii(str2)) -> will return True

Nouveautés de Python 3.7 ( bpo32677 )

Plus de contrôles ascii fastidieux / inefficaces sur les chaînes, nouvelle méthode str / octets / bytearray intégrée - .isascii () vérifiera si les chaînes sont ascii .

print("is this ascii?".isascii())
# True

Nous sommes récemment lancés dans quelque chose comme cela - 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')

Votre question est incorrecte. L'erreur que vous voyez ne résulte pas de la façon dont vous avez construit Python, mais d'une confusion entre les chaînes d'octets et les chaînes Unicode.

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

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

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

Cela vous indique la séquence de points de code " é " représente. Cela peut vous donner [233] ou vous donner [101, 770].

Au lieu de chr () pour inverser cette procédure, il existe unichr () :

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

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

La plupart du temps, vous ne devriez pas vous soucier de cela, mais cela peut devenir un problème si vous effectuez une itération sur une chaîne unicode, car l'itération fonctionne par point de code et non par un 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 les formulaires composés et décomposés en utilisant unicodedata.normalize .

Le glossaire Unicode peut être un guide utile pour comprendre certaines de ces questions en indiquant comment terme fait référence à une partie différente de la représentation du texte, ce qui est bien plus compliqué que ne le réalisent beaucoup de programmeurs.

Pourquoi ne pas faire cela?

import string

def isAscii(s):
    for c in s:
        if c not in string.ascii_letters:
            return False
    return True

Vincent Marchetti a la bonne idée, mais str.decode est obsolète en Python 3. En Python 3, vous pouvez effectuer le même test avec str.encode :

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

Notez que l'exception que vous souhaitez intercepter est également passée de UnicodeDecodeError à UnicodeEncodeError .

J'ai trouvé cette question en essayant de déterminer comment utiliser / encoder / décoder une chaîne dont l'encodage n'était pas sûr (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 ne m'étais pas rendu compte que je pouvais obtenir de bonnes données sur sa mise en forme à partir de type (s). Cette réponse a été très utile et a permis de trouver la véritable racine de mes problèmes.

Si vous avez un comportement grossier et persistant

  

UnicodeDecodeError: le codec 'ascii' ne peut pas décoder l'octet 0xc3 en position 263: l'ordinal n'est pas dans la plage (128)

surtout lorsque vous ENCODAGE, assurez-vous de ne pas essayer de faire unicode () une chaîne qui EST déjà unicode - pour une raison très terrible, vous obtenez des erreurs de codec Ascii. (Voir également la recette de cuisine Python , et le tutoriels Python pour une meilleure compréhension de la gravité de la situation.)

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

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

Le débogage a également été utile en définissant le codage par défaut de mon fichier sur utf-8 (placez-le au début de votre fichier python):

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

Cela vous permet de tester des caractères spéciaux ('& # 224; & # 233; & # 231;') sans avoir à utiliser leurs échappements Unicode (u '\ xe0 \ xe9 \ xe7').

>>> specials='àéç'
>>> specials.decode('latin-1').encode('ascii','xmlcharrefreplace')
'&#224;&#233;&#231;'

Pour améliorer la solution d'Alexander à partir de Python 2.6 (et de Python 3.x), vous pouvez utiliser le module auxiliaire curses.ascii et utiliser la fonction curses.ascii.isascii () ou une autre méthode: 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)

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

Un type sting (type str ) en Python est une série d'octets. Il n'y a aucun moyen de simplement dire à 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 autre.

Toutefois, si vous connaissez le codage utilisé, vous pouvez décoder la chaîne de caractères en chaîne Unicode, puis utiliser une expression régulière (ou une boucle) pour vérifier si elle contient des caractères extérieurs à la plage que vous avez définie. sont préoccupés.

Comme la réponse de @ RogerDahl, il est plus efficace de court-circuiter en annulant la classe de caractères et en utilisant la recherche au lieu de < code> find_all ou correspondance .

>>> 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.

Pour éviter que votre code ne se bloque, vous pouvez utiliser un try-except pour intercepter 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
import re

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

Pour inclure une chaîne vide au format ASCII, remplacez + par * .

, s))

Pour inclure une chaîne vide au format ASCII, remplacez + par * .

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
>>> 

Utilisez simplement un bloc conditionnel pour définir la fonction:

def is_ascii(input):
    if input.__class__.__name__ == "str":
        return True
    return False
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top