Je veux vérifier si une chaîne est en ASCII ou non.
Je suis au courant ord()
, cependant quand j'essaye ord('é')
, je l'ai TypeError: ord() expected a character, but string of length 2 found
. J'ai compris que cela est dû à la façon dont j'ai construit Python (comme expliqué dans ord()
la documentation de ).
Existe-t-il un autre moyen de vérifier?
Réponses:
la source
ord(c) < 128
est infiniment plus lisible et intuitif quec <= "\x7F"
Je pense que vous ne posez pas la bonne question ...
Une chaîne en python n'a pas de propriété correspondant à 'ascii', utf-8 ou tout autre encodage. La source de votre chaîne (que vous la lisiez à partir d'un fichier, 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 rechercher une réponse.
Peut-être la question que vous pouvez poser est: "Cette chaîne est-elle le résultat du codage d'une chaîne unicode en ascii?" - Vous pouvez y répondre en essayant:
la source
str
en Python 2,bytes
en Python 3).str
dans n'importe quel encodage ISO devrait d'abord être encodé en Unicode. La réponse devrait aller là-dedans.s.decode('ascii') if isinstance(s, bytes) else s.encode('ascii')
dans Python 3. L'entrée d'OP est un bytestring'é'
(syntaxe Python 2, Python 3 n'avait pas été publié à l'époque) et.decode()
est donc correcte.str
sur Python 2 est un bytestring. Il est correct d'utiliser.decode('ascii')
pour savoir si tous les octets sont dans la plage ascii.Python 3 voies:
Pour vérifier, passez la chaîne de test:
la source
isascii
c'est maintenant une fonction que vous passez une chaîne:isascii('somestring')
==True
etisascii('àéç')
==False
try: s.encode('ascii'); return True
except UnicodeEncodeError: return False
(comme ci-dessus, mais l'encodage, car les chaînes sont Unicode en Python 3). Cette réponse déclenche également une erreur dans Python 3 lorsque vous avez des substituts (par exemple,isascii('\uD800')
déclenche une erreur au lieu de revenirFalse
)Nouveau dans Python 3.7 ( bpo32677 )
Plus de contrôles ascii fastidieux / inefficaces sur les chaînes, nouvelle méthode /
str
/ intégrée - vérifiera si les chaînes sont ascii.bytes
bytearray
.isascii()
la source
"\x03".isascii()
est également vrai. La documentation indique que cela vérifie simplement que tous les caractères sont inférieurs au point de code 128 (0-127). Si vous voulez aussi éviter les caractères de contrôle, vous aurez besoin:text.isascii() and text.isprintable()
. L'utilisationisprintable
seule ne suffit pas non plus, car elle considérera qu'un caractère comme ¿est (correctement) imprimable, mais il ne fait pas partie de la section imprimable ascii, vous devez donc vérifier les deux si vous voulez les deux. Encore un autre problème: les espaces sont considérés comme imprimables, les tabulations et les nouvelles lignes ne le sont pas.Ran dans quelque chose comme ça récemment - pour référence future
que vous pourriez utiliser avec:
la source
{'confidence': 0.99, 'encoding': 'EUC-JP'}
(qui dans ce cas était complètement faux)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 avecstr.encode
:Notez que l'exception que vous souhaitez intercepter est également passée de
UnicodeDecodeError
àUnicodeEncodeError
.la source
bytes
tapez en Python 3 qui n'a pas de.encode()
méthode)..decode()
dans la réponse de @Vincent Marchetti est correcte .'é'
était un bytestring à l'époque.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 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; nombres de 0 à 255. Les chaînes Unicode (par exemple u "foo" ou u'bar ') sont des séquences de points de code Unicode; numéros de 0-1112064. Mais vous semblez 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 cela
ord(u'é')
, essayez ceci:Cela vous indique quelle séquence de points de code "é" représente. Cela peut vous donner [233], ou cela peut vous donner [101, 770].
Au lieu d'
chr()
inverser cela, il y aunichr()
:Ce caractère peut en fait être représenté soit par un ou plusieurs "points de code" unicode, qui eux-mêmes représentent soit des graphèmes soit des caractères. Il s'agit soit de "e avec un accent aigu (c'est-à-dire, point de code 233)", soit de "e" (point de code 101), suivi de "un accent aigu sur le caractère précédent" (point de code 770). Donc, ce même caractère exact peut être présenté comme la structure de données Python
u'e\u0301'
ouu'\u00e9'
.La plupart du temps, vous ne devriez pas vous soucier de cela, mais cela peut devenir un problème si vous itérez sur une chaîne unicode, car l'itération fonctionne par point de code, et non par caractère décomposable. En d'autres termes,
len(u'e\u0301') == 2
etlen(u'\u00e9') == 1
. Si cela vous intéresse, vous pouvez convertir entre les formes composées et décomposées à l'aide deunicodedata.normalize
.Le glossaire Unicode peut être un guide utile pour comprendre certains de ces problèmes, en montrant comment chaque terme spécifique fait référence à une partie différente de la représentation du texte, ce qui est beaucoup plus compliqué que ne le pensent de nombreux programmeurs.
la source
Et si on faisait ça?
la source
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 ne savais pas que je pouvais obtenir de bonnes données sur sa mise en forme à partir des types. Cette réponse a été très utile et est arrivée à la véritable racine de mes problèmes.
Si vous obtenez un grossier et persistant
en particulier lorsque vous ENCODEZ, assurez-vous que vous n'essayez pas d'Unicode () une chaîne qui EST déjà UNICODE - pour une raison terrible, vous obtenez des erreurs de codec ascii. (Voir aussi la recette Python Kitchen et les documents Python didacticiels pour mieux comprendre à quel point cela peut être terrible.)
Finalement, j'ai déterminé que ce que je voulais faire était le suivant:
Le débogage a également été utile en définissant le codage par défaut de mon fichier sur utf-8 (mettez cela au début de votre fichier python):
Cela vous permet de tester des caractères spéciaux ('àéç') sans avoir à utiliser leurs échappements Unicode (u '\ xe0 \ xe9 \ xe7').
la source
Pour améliorer la solution d'Alexander à partir de Python 2.6 (et dans Python 3.x), vous pouvez utiliser le module d'assistance curses.ascii et utiliser la fonction curses.ascii.isascii () ou diverses autres: https://docs.python.org/2.6/ bibliothèque / curses.ascii.html
la source
curses.ascii
Vous pouvez utiliser la bibliothèque d'expressions régulières qui accepte la définition standard de Posix [[: ASCII:]].
la source
Une piqûre (
str
-type) en Python est une série d'octets. Il n'y a aucun moyen 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 codée avec UTF-8 ou UTF-16 ou autre .Cependant, si vous connaissez l'encodage utilisé, vous pouvez
decode
transformer la chaîne en chaîne unicode, puis 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 préoccupe.la source
Comme la réponse de @ RogerDahl, mais il est plus efficace de court-circuiter en annulant la classe de caractères et en utilisant la recherche au lieu de
find_all
oumatch
.J'imagine qu'une expression régulière est bien optimisée pour cela.
la source
Pour inclure une chaîne vide au format ASCII, remplacez
+
par*
.la source
Pour éviter que votre code ne plante, vous souhaiterez peut-être utiliser un
try-except
pour intercepterTypeErrors
Par exemple
la source
try
emballage est complètement inutile. Si"¶"
est une chaîne Unicode, alorsord("¶")
fonctionnera, et si ce n'est pas le cas (Python 2), lafor c in s
décomposera en octets etord
continuera de fonctionner.J'utilise ce qui suit pour déterminer si la chaîne est ascii ou unicode:
Utilisez ensuite un bloc conditionnel pour définir la fonction:
la source
is_ascii(u'i am ascii')
. Même si les lettres et les espaces sont définitivement ASCII, cela revient quand mêmeFalse
parce que nous avons forcé la chaîne à l'êtreunicode
.