¿Cómo comprobar 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 intento ord('é'), he TypeError: ord() expected a character, but string of length 2 found. Entendí que es causada por la forma en que construí Python (como se explica en ord()'s documentation).

¿Hay otra manera de comprobar?

Author: Amir, 2008-10-13

16 answers

def is_ascii(s):
    return all(ord(c) < 128 for c in s)
 135
Author: Alexander Kojevnikov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-13 00:30:43

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 (si la lee 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 necesita ir para una respuesta.

Tal vez la pregunta que puede hacerse es: "¿Es esta cadena el resultado de codificar una cadena unicode en ascii?"This Esto se puede respuesta al intentar:

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
Author: Vincent Marchetti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-13 00:30:32

Python 3 way:

isascii = lambda s: len(s) == len(s.encode())
 120
Author: far,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-19 13:05:58

Se 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 podrías usar con:

string_ascii = string.decode(encoding['encoding']).encode('ascii')
 18
Author: Alvin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-08 20:47:22

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

Las cadenas de bytes (por ejemplo, "foo", o 'bar', en la sintaxis de python) son secuencias de octetos; números del 0 al 255. Las cadenas Unicode (por ejemplo, u"foo" o u'bar') son secuencias de puntos de código unicode; números de 0 a 1112064. Pero usted parece estar interesado en el carácter é, que (en su terminal) es una secuencia multi-byte que representa una sola caracter.

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

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

Que le dice qué secuencia de puntos de código "é" representa. Puede darte [233], o puede darte [101, 770].

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

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

Este carácter puede ser representado ya sea uno o varios "puntos de código" unicode, que a su vez representan grafemas o caracteres. Es "e con un acento agudo (es decir, punto de código 233)", o " e " (código punto 101), seguido de "un acento agudo en el carácter anterior" (código 770). Así que este mismo carácter puede ser presentado como la estructura de datos de Python u'e\u0301' o u'\u00e9'.

La mayoría de las veces no debería tener que 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 formas compuestas y descompuestas por usando unicodedata.normalize.

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

 17
Author: Glyph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-08 02:10:02

¿Qué tal hacer esto?

import string

def isAscii(s):
    for c in s:
        if c not in string.ascii_letters:
            return False
    return True
 10
Author: miya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-13 16:38:25

Vincent Marchetti tiene la idea correcta, pero str.decode ha sido obsoleto en Python 3. En Python 3 puedes 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.

 9
Author: drs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-02 15:45:04

Encontré esta pregunta mientras intentaba determinar cómo usar/codificar/decodificar una cadena cuya codificación 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 su formato de tipo(s). Esta respuesta fue muy útil y llegó a la raíz real de mis problemas.

Si usted está recibiendo un grosero y persistente

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

Particularmente cuando estás CODIFICANDO, asegúrate de no intentar unicode() una cadena que ya es unicode - por alguna terrible razón, obtienes errores de códec ascii. (Ver también el Python Kitchen recipe , y el Python docs tutoriales para una mejor comprensión de lo terrible que esto puede ser.)

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

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

También fue útil en la depuración establecer la codificación predeterminada en mi archivo a utf-8 (pon esto al principio de tu archivo python):

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

Que 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;'
 8
Author: Max P Magee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:10

Para mejorar la solución de Alexander desde Python 2.6 (y en Python 3.x) puede usar maldiciones de módulos auxiliares.ascii y usa maldiciones.ASCII.función 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)
 4
Author: Sergey Nevmerzhitsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-22 09:17:16

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

 2
Author: Steve Moyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-13 00:18:25

Un sting (str-type) en Python es una serie de bytes. No hay manera de decir solo mirando la cadena si esta serie de bytes representan una cadena ascii, una cadena en un conjunto 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, entonces puede decode el str en una cadena unicode y luego usar una expresión regular (o un bucle) para verificar si contiene caracteres fuera del rango que está preocupado por.

 2
Author: JacquesB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-14 08:10:06

Nuevo en Python 3.7 (bpo32677)

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

print("is this ascii?".isascii())
# True
 2
Author: abccd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-02 18:32:22

Para evitar que su código se bloquee, tal vez desee usar un try-except para atrapar 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
 0
Author: Sebastian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-07 21:16:00
import re

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

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

 0
Author: Roger Dahl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-30 14:51:52

Como la respuesta de @RogerDahl pero es más eficiente cortocircuitar negando la clase de caracteres y usando 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

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

 0
Author: hobs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:24

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

Entonces simplemente use un bloque condicional para definir la función:

def is_ascii(input):
    if input.__class__.__name__ == "str":
        return True
    return False
 -4
Author: user397587,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-21 06:34:56