¿Cómo verificar si una cadena en Python está en ASCII?

Quiero comprobar si una cadena está en ASCII o no.

Soy consciente de ord() , sin embargo, cuando bash ord('é') , TypeError: ord() expected a character, but string of length 2 found . Entendí que se debe a la forma en que construí Python (como se explica en la documentación de ord() ).

¿Hay otra forma de comprobarlo?

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

Creo que no estás haciendo la pregunta correcta–

Una cadena en python no tiene propiedad correspondiente a ‘ascii’, utf-8, o cualquier otra encoding. La fuente de su cadena (ya sea que la lea desde un archivo, la entrada desde un teclado, etc.) puede haber codificado una cadena Unicode en ascii para producir su cadena, pero ahí es donde debe ir para obtener una respuesta.

Quizás la pregunta que puede hacerse es: “¿Es esta cadena el resultado de codificar una cadena Unicode en ascii?” – Esto lo puedes contestar intentando:

 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 vías:

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

Encontré algo como esto recientemente, para futuras referencias

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

que podrías usar con:

 string_ascii = string.decode(encoding['encoding']).encode('ascii') 

Tu pregunta es incorrecta; El error que ve no es el resultado de cómo construyó Python, sino una confusión entre las cadenas de bytes y las cadenas de Unicode.

Las cadenas de bytes (por ejemplo, “foo”, o ‘barra’, en la syntax de Python) son secuencias de octetos; Números del 0-255. Las cadenas Unicode (por ejemplo, u “foo” o u’bar ‘) son secuencias de puntos de código Unicode; Números del 0-1112064. Pero parece que estás interesado en el carácter é, que (en tu terminal) es una secuencia de múltiples bytes que representa un solo carácter.

En lugar de ord(u'é') , intente esto:

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

Eso te dice qué secuencia de puntos de código representa “é”. Puede darle [233], o puede darle [101, 770].

En lugar de chr() para revertir esto, hay unichr() :

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

Este carácter puede representarse en realidad en uno o varios “puntos de código” Unicode, que a su vez representan grafemas o caracteres. Es “e con acento agudo (es decir, punto de código 233)” o “e” (punto de código 101), seguido de “acento agudo en el carácter anterior” (punto de código 770). Por lo tanto, este mismo carácter exacto se puede presentar como la estructura de datos de Python u'e\u0301' u u'\u00e9' .

La mayoría de las veces no debería preocuparse por esto, pero puede convertirse en un problema si está iterando sobre una cadena Unicode, ya que la iteración funciona por punto de código, no por carácter descomponible. En otras palabras, len(u'e\u0301') == 2 y len(u'\u00e9') == 1 . Si esto es importante para usted, puede convertir entre formas compuestas y descompuestas utilizando unicodedata.normalize .

El Glosario de Unicode puede ser una guía útil para comprender algunos de estos problemas, al señalar cómo cada término específico se refiere a una parte diferente de la representación del texto, que es mucho más complicada de lo que muchos progtwigdores se dan cuenta.

Nuevo en Python 3.7 ( bpo32677 )

Ya no es más molesto / ineficiente comprobar las cadenas, el nuevo método incorporado str / bytes / bytearray.isascii() comprobará si las cadenas son ascii.

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

¿Qué tal hacer esto?

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

Vincent Marchetti tiene la idea correcta, pero str.decode ha sido desaprobado en Python 3. En Python 3 puede hacer la misma prueba con str.encode :

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

Tenga en cuenta que la excepción que desea capturar también ha cambiado de UnicodeDecodeError a UnicodeEncodeError .

Encontré esta pregunta al intentar determinar cómo usar / codificar / decodificar una cadena cuya encoding no estaba seguro (y cómo escapar / convertir caracteres especiales en esa cadena).

Mi primer paso debería haber sido comprobar el tipo de la cadena. No me di cuenta de que podía obtener buenos datos sobre el formato de los tipos. Esta respuesta fue muy útil y llegó a la verdadera raíz de mis problemas.

Si te estás volviendo rudo y persistente.

UnicodeDecodeError: el codec ‘ascii’ no puede decodificar el byte 0xc3 en la posición 263: ordinal no está dentro del rango (128)

particularmente cuando está codificado, asegúrese de no intentar unicode () una cadena que ya es unicode; por alguna terrible razón, obtiene errores de códec ASCII. (Consulte también la receta de Python Kitchen y los tutoriales de los documentos de Python para comprender mejor lo terrible que puede ser esto).

Finalmente determiné que lo que quería hacer era esto:

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

También fue útil para la depuración establecer la encoding predeterminada en mi archivo en utf-8 (ponga esto al principio de su archivo de Python):

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

Eso le permite probar caracteres especiales (‘àéç’) sin tener que usar sus escapes de Unicode (u ‘\ xe0 \ xe9 \ xe7’).

 >>> specials='àéç' >>> specials.decode('latin-1').encode('ascii','xmlcharrefreplace') 'àéç' 

Para mejorar la solución de Alexander desde Python 2.6 (y en Python 3.x) puede usar el módulo de ayuda curses.ascii y usar la función curses.ascii.isascii () o varias otras: 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) 

Podría usar la biblioteca de expresiones regulares que acepta la definición estándar de [[: ASCII:]] de Posix.

Una picadura ( str -type) en Python es una serie de bytes. No hay forma de saber simplemente viendo la cadena si esta serie de bytes representa una cadena ASCII, una cadena en un juego de caracteres de 8 bits como ISO-8859-1 o una cadena codificada con UTF-8 o UTF-16 o lo que sea .

Sin embargo, si conoce la encoding utilizada, puede decode la cadena en una cadena Unicode y luego usar una expresión regular (o un bucle) para verificar si contiene caracteres fuera del rango que le preocupa.

Para evitar que su código se bloquee, tal vez quiera usar un try-except para capturar TypeErrors

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

Por ejemplo

 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]+$', s)) 

Para incluir una cadena vacía como ASCII, cambie el + a * .

Me gusta la respuesta de @ RogerDahl pero es más eficiente hacer un cortocircuito al anular la clase de personaje y usar la búsqueda en lugar de find_all o 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 

Me imagino que una expresión regular está bien optimizada para esto.

Uso lo siguiente para determinar si la cadena es ascii o unicode:

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

Luego solo usa un bloque condicional para definir la función:

 def is_ascii(input): if input.__class__.__name__ == "str": return True return False