Pregunta

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

Soy consciente de ord () , sin embargo, cuando intento ord ('é') , tengo TypeError: ord () esperaba un carácter, pero se encontró una cadena de longitud 2 . Comprendí que es causado por la forma en que construí Python (como se explica en ord () documentación de ).

¿Hay otra forma de verificar?

¿Fue útil?

Solución

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

Otros consejos

Creo que no estás haciendo la pregunta correcta--

Una cadena en python no tiene ninguna propiedad correspondiente a 'ascii', utf-8 o cualquier otra codificación. 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 buscar una respuesta.

Quizás la pregunta que puede hacer es: "¿Es esta cadena el resultado de codificar una cadena unicode en ascii?" - Esto puedes responder     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())

Para verificar, pase la cadena de prueba:

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

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

Nuevo en Python 3.7 ( bpo32677 )

No más verificaciones ascii tediosas / ineficientes en cadenas, nuevo método str / bytes / bytearray incorporado - .isascii () comprobará si las cadenas son ascii .

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

Me encontré con algo como esto recientemente - para referencia futura

import chardet

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

que puedes usar con:

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

Su pregunta es incorrecta; el error que ve no es el resultado de cómo creó Python, sino de una confusión entre cadenas de bytes y cadenas unicode.

Las cadenas de bytes (por ejemplo, '' foo '' o 'bar', en sintaxis 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 estar interesado en el carácter & # 233 ;, que (en su terminal) es una secuencia de varios bytes que representa un solo carácter.

En lugar de ord (u '& # 233;') , intente esto:

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

Eso le indica qué secuencia de puntos de código " & # 233; " representa. Puede darle [233], o puede darle [101, 770].

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

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

En realidad, este carácter puede representarse como 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 "un 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 ' o 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 le importa, puede convertir entre formularios compuestos y descompuestos utilizando unicodedata.normalize .

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

¿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 quedado en desuso 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 detectar también ha cambiado de UnicodeDecodeError a UnicodeEncodeError .

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

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

Si obtienes una actitud grosera y persistente

  

UnicodeDecodeError: el códec 'ascii' no puede decodificar el byte 0xc3 en la posición 263: el ordinal no está en el rango (128)

particularmente cuando está CODIFICANDO, asegúrese de que no está intentando unicode () una cadena que ya ES unicode- por alguna razón terrible, obtiene errores de códec ASCII. (Consulte también la receta de Python Kitchen , y la Python docs tutoriales 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 codificación predeterminada en mi archivo a utf-8 (pon esto al comienzo de tu archivo de Python):

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

Eso le permite probar caracteres especiales ('àéç') sin tener que usar sus escapes unicode (u '\ xe0 \ xe9 \ xe7').

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

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

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

Una picadura ( str -type) en Python es una serie de bytes. no hay forma de decir simplemente mirando 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 codificación utilizada, puede decodificar la cadena en una cadena unicode y luego usar una expresión regular (o un bucle) para verificar si contiene caracteres fuera del rango están preocupados.

Al igual que la respuesta de @ RogerDahl, pero es más eficiente hacer un cortocircuito al negar la clase de caracteres y usar la búsqueda en lugar de < code> 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.

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 "<stdin>", line 1, in <module>
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]+

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

, s))

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

Utilizo 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 use un bloque condicional para definir la función:

def is_ascii(input):
    if input.__class__.__name__ == "str":
        return True
    return False
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top