2010-09-03 15 views
19

Mam kod pobierający dane z portu COM i chcę się upewnić, że to, co mam naprawdę, to ciąg do drukowania (np. ASCII, może UTF-8) przed jego wydrukowaniem. Czy istnieje funkcja do tego? Pierwsze miejsca doży, które wyglądałem, nie miały niczego, co wyglądałoby jak chcę. (string has printable ale nie widzę nic (lub nie w the string methods), aby sprawdzić, czy każdy znak w jeden ciąg jest w innymSprawdź, czy ciąg znaków Pythona jest możliwy do wydrukowania.

. Uwaga: znaki sterujące są nie wydruku dla moich celów


.

Edit: byłem/szukam jednej funkcji, a nie przewróceniu własne rozwiązanie:

Co skończyło się jest:

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

Jeśli nie ma gotowe rozwiązanie, można DIY z 'string.printable':' printables = set (string.printable); jeśli wszystko (char w printables dla char w your_string): ... ' – delnan

Odpowiedz

3

try/except wydaje się, że najlepszym sposobem:

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

nie będę polegać na string.printable, co może uznają za „non-printable” znaki sterujące, które mogą często być „wydrukowane” do celów kontroli końcowych (na przykład w " colorization "Sekwencje specjalne ANSI, jeśli twój terminal jest zgodny z ANSI). Ale to, oczywiście, zależy od dokładnych celów, dla chcących sprawdzić -)

+2

string.printable jest dobrze zdefiniowany. "kombinacja cyfr, liter, znaków interpunkcyjnych i białych znaków". Whitesapce OTOH jest nieco mniejszy: "W większości systemów obejmuje to przestrzeń znaków, tabulację, linefeed, return, formfeed i pionową kartę". – BCS

+2

@BCS, to w zasadzie ta sama koncepcja, co złe, stare makro 'isprint' firmy C, i wykazuje dokładnie te same błędy (brak sekwencji kontrolnych/sekwencji unikowych - ale wiele terminali i drukarek może zaakceptować pewne sekwencje kontrolne/sekwencje specjalne w celach kosmetycznych, takich jak kolorowanie oraz, w zależności od celów aplikacji, zabranianie takich znaków z wyjścia może okazać się nierozsądne). –

+0

Obawiam się, że białe spacje mogą zawierać * więcej * niż te 6 znaków. Wiem, że jeśli moje źródło danych zawiera kiedykolwiek "znaki kontrolne", mogę założyć, że są to śmieci. – BCS

36

Jak już powiedział string module has printable więc jest to tylko przypadek sprawdzenie czy wszystkie znaki w swoim ciągiem są w 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 

można konwertować oba ciągi do zbiorów - więc zestaw będzie zawierać każdy znak w łańcuchu raz - i sprawdzić, czy zestaw stworzony przez ciąg is a subset of do druku znaków:

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

więc w skrócie , Prawdopodobnie chcesz to zrobić:

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

Miałem nadzieję, że nie rozwiążę twojego rozwiązania. Dlaczego do cholery nie python mają to jako funkcję? – BCS

+6

"Dlaczego do cholery nie python ma to jako funkcję?": To rozwiązanie, i inne podobne, to trywialne kompozycje wbudowanych obiektów python. jeśli nadano mu specjalną nazwę, a każda inna użyteczna, ale trywialna cecha została również pobłogosławiona nazwą, wówczas przestrzeń nazw Pythona byłaby niepoprawnie zagracona. ta krótka kompozycja jest tak samo czytelna, jak niektóre hipotetyczne 'stringutil.stringisprintable (myvar)', z tym że nie ma potrzeby utrzymywania tego dodatkowego modułu. – SingleNegationElimination

+3

Czy obsługuje to cokolwiek poza 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

To jest trochę zbyt sprytne. Prawdopodobnie nie powinieneś tego robić, ale +1 tak czy inaczej, ponieważ sprawiło, że się uśmiecham. – SingleNegationElimination

+4

działa tylko dla ascii. – BCS

+4

Niepowodzenie dla 's = 'a \ nb''. –

Powiązane problemy