separar - ¿Cómo comprobar si una cadena en Python está en ASCII?
reemplazar caracteres en python (15)
Quiero comprobar si una cadena está en ASCII o no.
Soy consciente de ord()
, sin embargo, cuando intento ord(''é'')
, tengo TypeError: ord() expected a character, but string of length 2 found
. Entendí que es causado por la forma en que construí Python (como se explica en la documentación de ord()
).
¿Hay alguna otra manera de verificar?
¿Qué hay de hacer esto?
import string
def isAscii(s):
for c in s:
if c not in string.ascii_letters:
return False
return True
Como la answer @ RogerDahl, pero es más eficiente hacer un cortocircuito al negar 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.
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, entrada desde un teclado, etc.) puede haber codificado una cadena Unicode en ASCII para producir su cadena, pero ahí es donde necesita obtener una respuesta.
Quizás la pregunta que puede hacerse es: "¿Es esta cadena el resultado de codificar una cadena Unicode en ASCII?" - Esto puede responder intentándolo:
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"
Encontré algo así 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'')
Encontré esta pregunta al intentar 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 verificar el tipo de cadena; no me di cuenta de que allí podía obtener buenos datos sobre su formato de tipo (s). Esta respuesta fue muy útil y llegó a la verdadera raíz de mis problemas.
Si te estás volviendo grosero 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á tratando de unicode () una cadena que ya es unicode, por alguna razón terrible, usted obtiene errores de códec ascii. (Consulte también la receta de Python Kitchen y los tutoriales de Python para comprender mejor cuán terrible 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 en la depuración establecer la codificación predeterminada en mi archivo para utf-8 (poner esto al principio de su archivo 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'')
''àéç''
Para evitar que su código falle, 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
Para mejorar la solución de Alexander desde el 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 otras varias: 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 acepte la definición de estándar Posix [[: ASCII:]].
Python 3 vías:
isascii = lambda s: len(s) == len(s.encode())
Tu pregunta es incorrecta; el error que ves no es resultado de cómo construiste 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-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 pareces estar 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 darte [233] o puede darte [101, 770].
En lugar de chr()
para revertir esto, hay unichr()
:
>>> unichr(233)
u''/xe9''
Este personaje en realidad puede representarse como un único o múltiples "puntos de código" unicode, que a su vez representan grafemas o caracteres. Es "e con un acento agudo (es decir, código de punto 233)" o "e" (código de punto 101), seguido de "un acento agudo en el carácter anterior" (código de punto 770). Entonces, este mismo personaje se puede presentar como la estructura de datos de Python u''e/u0301''
or 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 formularios compuestos y descompuestos utilizando unicodedata.normalize
.
El Glosario Unicode puede ser una guía útil para comprender 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, que es mucho más complicado de lo que muchos programadores se dan cuenta.
Un sting ( 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 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 le preocupa.
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
>>>
Entonces solo usa un bloque condicional para definir la función:
def is_ascii(input):
if input.__class__.__name__ == "str":
return True
return False
Vincent Marchetti tiene la idea correcta, pero str.decode
ha quedado 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 captura también ha cambiado de UnicodeDecodeError
a UnicodeEncodeError
.
def is_ascii(s):
return all(ord(c) < 128 for c in s)
import re
def is_ascii(s):
return bool(re.match(r''[/x00-/x7F]+$'', s))
Para incluir una cadena vacía como ASCII, cambie +
a *
.