2010-09-03 17 views
19

Ho un codice che estrae i dati da una com-port e voglio assicurarmi che quello che ho ottenuto sia una stringa stampabile (ad esempio ASCII, forse UTF-8) prima di stamparla. C'è una funzione per farlo? I posti dozon della prima metà che ho guardato non avevano nulla che assomiglia a quello che voglio. (string has printable ma non ho visto nulla (lì o in the string methods) per verificare se ogni carattere in una stringa è in un altroVerifica se una stringa python è stampabile

. Nota: i caratteri di controllo sono non stampabile per i miei scopi


.

Edit: ero/Cerco una singola funzione, non un rotolo la vostra soluzione:

Quello che ho finito con è:

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

Se non c'è soluzione pronta all'uso, è possibile fai da te con 'string.printable':' stampabili = set (string.printable); if all (char in stampabili per char in your_string): ... ' – delnan

risposta

3

try/except sembra il modo migliore:

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

non fare affidamento su di string.printable, che potrebbe ritenere caratteri di controllo "non stampabili" che possono comunemente essere "stampate" ai fini del controllo del terminale (ad esempio, in " colorizzazione "Sequenze di escape ANSI, se il terminale è conforme ANSI). Ma questo, naturalmente, dipende dalle vostre scopi precisi per voler controllare questo -)

+2

string.printable è ben definito. "una combinazione di cifre, lettere, punteggiatura e spazi bianchi". Whitesapce OTOH è un po 'meno: "Nella maggior parte dei sistemi questo include spazio per i caratteri, scheda, avanzamento riga, ritorno, formfeed e scheda verticale." – BCS

+2

@BCS, è fondamentalmente lo stesso concetto della vecchia e cattiva macro 'isprint' di C e presenta esattamente gli stessi errori (nessuna sequenze di controllo/sequenze di escape - ma molti terminali e stampanti possono accettare alcune sequenze di controllo/escape per scopi cosmetici come colorizzazione e, a seconda degli scopi dell'app, vietare tali caratteri dall'output potrebbe quindi rivelarsi imprudente). –

+0

La mia preoccupazione è che lo spazio bianco possa includere * più * di quei 6 caratteri. So che se la mia fonte di dati contiene mai "caratteri di controllo", posso presumere che siano spazzatura. – BCS

36

Come hai detto la string module has printable quindi è solo un caso di verificare se tutti i caratteri nella stringa sono in 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 

Si potrebbe convertire entrambe le stringhe ai set - così il set conterrebbe ogni carattere della stringa una volta - e verificare se l'insieme creato da stringa is a subset of i caratteri stampabili:

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

così, in sintesi , Si sarebbe probabilmente vuole fare questo:

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

Speravo in un non-roll per la tua soluzione. Perché diavolo Python non ha questo come una funzione? – BCS

+6

"Perché diamine, Python non ha questa funzione come funzione?": Questa soluzione, e altre simili, sono composizioni banali di funzioni built-in python. se questo è stato dato un nome speciale, e ogni altra caratteristica utile ma banale è stata benedetta con un nome, quindi lo spazio dei nomi python sarebbe stato ingombrante. questa breve composizione è tanto leggibile quanto alcuni ipotetici 'stringutil.stringisprintable (myvar)', tranne per il fatto che non è necessario mantenere quel modulo aggiuntivo. – SingleNegationElimination

+3

Gestisce qualcosa oltre l'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

Questo è solo un po 'troppo intelligente. Probabilmente non dovresti farlo, ma +1 in ogni caso perché mi ha fatto sorridere. – SingleNegationElimination

+4

funziona solo per ASCII. – BCS

+4

Fallisce per 's = 'a \ nb''. –

Problemi correlati