2010-09-03 27 views
19

Tengo un código que extrae datos de un puerto de comunicaciones y quiero asegurarme de que lo que obtuve realmente sea una cadena imprimible (es decir, ASCII, tal vez UTF-8) antes de imprimirlo. ¿Hay una función para hacer esto? La primera mitad de dozon lugares que miré no tenía nada que se parece a lo que quiero. (string has printable pero no vi nada (allí o en the string methods) para comprobar si cada caracter en una cadena está en otroPrueba si una cadena de python es imprimible

. Nota: los caracteres de control son no imprimible para mis propósitos


.

Edit: era/Busco una sola función, no un rollo de su propia solución:

Lo que terminé con es:

all(ord(c) < 127 and c in string.printable for c in input_str) 
+0

Si no hay una solución lista para usar, usted puede DIY con 'string.printable':' printables = set (string.printable); if all (char en imprimibles para char en your_string): ... ' – delnan

Respuesta

3

try/except parece la mejor manera:

def isprintable(s, codec='utf8'): 
    try: s.decode(codec) 
    except UnicodeDecodeError: return False 
    else: return True 

yo no confiaría en string.printable, lo que podría considerar que los caracteres de control "no imprimibles" que comúnmente se puede "imprimir" para los propósitos de control terminal (por ejemplo, en " colorización "Secuencias de escape ANSI, si su terminal cumple con ANSI). Pero eso, por supuesto, depende de sus efectos exactos para querer comprobar esto -)

+2

string.printable está bien definido. "una combinación de dígitos, letras, signos de puntuación y espacios en blanco". Whitesapce OTOH es un poco menos: "En la mayoría de los sistemas, esto incluye el espacio de caracteres, tabulación, salto de línea, retorno, avance de formulario y tabulación vertical". – BCS

+2

@BCS, básicamente es el mismo concepto que la antigua macro 'isprint' de C, y muestra exactamente las mismas fallas (sin secuencias de control/secuencias de escape), pero muchos terminales e impresoras pueden aceptar algunas secuencias de control/escape con fines cosméticos, como la coloración, y, dependiendo de los propósitos de la aplicación, prohibir tales caracteres de la salida puede por lo tanto probarse imprudente). –

+0

Mi preocupación es que el espacio en blanco podría incluir * más * que esos 6 caracteres. Sé que si mi fuente de datos contiene alguna vez "caracteres de control", puedo suponer que son basura. – BCS

36

Como usted ha dicho la string module has printable por lo que es sólo un caso de comprobar si todos los caracteres en la cadena están en printable:

>>> hello = 'Hello World!' 
>>> bell = chr(7) 
>>> import string 
>>> all(c in string.printable for c in hello) 
True 
>>> all(c in string.printable for c in bell) 
False 

Se podría convertir las dos cadenas de conjuntos - por lo que el conjunto contendrían cada carácter de la cadena una vez - y comprobar si el conjunto creado por la cadena de is a subset of los caracteres imprimibles:

>>> printset = set(string.printable) 
>>> helloset = set(hello) 
>>> bellset = set(bell) 
>>> helloset 
set(['!', ' ', 'e', 'd', 'H', 'l', 'o', 'r', 'W']) 
>>> helloset.issubset(printset) 
True 
>>> set(bell).issubset(printset) 
False 

así, en resumen , Es probable que desee hacer esto:

import string 
printset = set(string.printable) 
isprintable = set(yourstring).issubset(printset) 
+4

Tenía la esperanza de que tu propia solución fuera de rollo. ¿Por qué diablos no tiene Python esto como una función? – BCS

+6

"¿Por qué diablos no tiene esto como función python?": Esta solución, y otras similares, son composiciones triviales de las instalaciones de python integradas. si a esto se le dio un nombre especial, y cada otra característica útil pero trivial también fue bendecida con un nombre, entonces el espacio de nombres de python sería abismalmente desordenado. esta breve composición es tan legible como un hipotético 'stringutil.stringisprintable (myvar)', excepto que no hay necesidad de mantener ese módulo adicional. – SingleNegationElimination

+3

¿Esto maneja algo más allá de ASCII? – jpmc26

3
>>> # Printable 
>>> s = 'test' 
>>> len(s)+2 == len(repr(s)) 
True 

>>> # Unprintable 
>>> s = 'test\x00' 
>>> len(s)+2 == len(repr(s)) 
False 
+6

Esto es demasiado inteligente. Probablemente no deberías hacer esto, pero +1 de todos modos porque me hizo sonreír. – SingleNegationElimination

+4

solo funciona para ascii. – BCS

+4

Falla para 's = 'a \ nb''. –

Cuestiones relacionadas