Проверьте, доступна ли строка python
У меня есть некоторый код, который извлекает данные из com-порта, и я хочу убедиться, что то, что я получил, действительно является строкой для печати (т.е. ASCII, может быть, UTF-8) перед печатью. Есть ли функция для этого? Первые полдюжины мест, которые я посмотрел, не имели ничего похожего на то, что я хочу. (строка имеет возможность печати, но я не видел ничего (там или в методах строки), чтобы проверить, есть ли каждый символ в одной строке в другом.
Примечание: управляющие символы не могут быть напечатаны для моих целей.
Редактировать: я искал/ищу единственную функцию, а не решение по собственной инициативе:
В итоге я получил:
all(ord(c) < 127 and c in string.printable for c in input_str)
Ответы
Ответ 1
Как вы сказали, модуль string
имеет printable
, поэтому он просто проверяет, все ли символы в вашей строке находятся в 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
Вы можете преобразовать обе строки в множества - поэтому набор будет содержать каждый символ в строке один раз - и проверить, является ли набор, созданный вашей строкой подмножеством из печатаемых символов:
>>> 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
Итак, в общем, вы, вероятно, захотите сделать это:
import string
printset = set(string.printable)
isprintable = set(yourstring).issubset(printset)
Ответ 2
try
/except
выглядит наилучшим образом:
def isprintable(s, codec='utf8'):
try: s.decode(codec)
except UnicodeDecodeError: return False
else: return True
Я бы не стал полагаться на string.printable
, который мог бы считать "непечатаемыми" управляющими символами, которые обычно могут быть "распечатаны" для целей управления терминалом (например, в "красящих" ANSI escape-последовательностях, если ваш терминал ANSI- совместимый). Но это, конечно, зависит от ваших точных целей от желания проверить это! -)
Ответ 3
>>> # Printable
>>> s = 'test'
>>> len(s)+2 == len(repr(s))
True
>>> # Unprintable
>>> s = 'test\x00'
>>> len(s)+2 == len(repr(s))
False
Ответ 4
Эта строка Python 3 содержит все виды специальных символов:
s = 'abcd\x65\x66 äüöë\xf1 \u00a0\u00a1\u00a2 漢字 \a\b\r\t\n\v\\ \231\x9a \u2640\u2642\uffff'
Если вы попытаетесь показать его в консоли (или использовать repr
), он довольно хорошо удалит все непечатаемые символы из этой строки:
>>> s
'abcdef äüöëñ \xa0¡¢ 漢字 \x07\x08\r\t\n\x0b\\ \x99\x9a ♀♂\uffff'
Он достаточно умен, чтобы распознавать, например, горизонтальную вкладку (\t
) как печатаемую, а вертикальную вкладку (\v
) как не печатаемую (отображается как \x0b
а не \v
).
Любой другой не печатаемый символ также отображается как либо \xNN
или \uNNNN
в repr
. Поэтому мы можем использовать это в качестве теста:
def is_printable(s):
return not any(repr(ch).startswith("'\\x") or repr(ch).startswith("'\\u") for ch in s)
Могут быть некоторые пограничные символы, например, неразрывный пробел (\xa0
) здесь рассматривается как непечатный. Может быть, и не должно быть, но эти специальные могут быть жестко закодированы.
PS
Вы можете сделать это, чтобы извлечь только печатные символы из строки:
>>> ''.join(ch for ch in s if is_printable(ch))
'abcdef äüöëñ ¡¢ 漢字 \r\t\n\\ ♀♂'
Ответ 5
Функция category
из модуля unicodedata
может удовлетворить ваши потребности. Например, вы можете использовать это, чтобы проверить, есть ли какие-либо управляющие символы в строке, в то же время позволяя использовать символы не ASCII.
>>> import unicodedata
>>> def has_control_chars(s):
... return any(unicodedata.category(c) == 'Cc' for c in s)
>>> has_control_chars('Hello 世界')
False
>>> has_control_chars('Hello \x1f 世界')
True
Ответ 6
Мое решение - избавиться от любого известного набора символов. это может помочь.
non_printable_chars = set("\n\t\r ") # Space included intensionally
is_printable = lambda string:bool(set(string) - set(non_printable_chars))
...
...
if is_printable(string):
print("""do something""")
...
Ответ 7
ctrlchar = "\n\r| "
# ------------------------------------------------------------------------
# This will let you control what you deem 'printable'
# Clean enough to display any binary
def isprint(chh):
if ord(chh) > 127:
return False
if ord(chh) < 32:
return False
if chh in ctrlchar:
return False
if chh in string.printable:
return True
return False
Ответ 8
# Here is the full routine to display an arbitrary binary string
# Python 2
ctrlchar = "\n\r| "
# ------------------------------------------------------------------------
def isprint(chh):
if ord(chh) > 127:
return False
if ord(chh) < 32:
return False
if chh in ctrlchar:
return False
if chh in string.printable:
return True
return False
# ------------------------------------------------------------------------
# Return a hex dump formatted string
def hexdump(strx, llen = 16):
lenx = len(strx)
outx = ""
for aa in range(lenx/16):
outx += " "
for bb in range(16):
outx += "%02x " % ord(strx[aa * 16 + bb])
outx += " | "
for cc in range(16):
chh = strx[aa * 16 + cc]
if isprint(chh):
outx += "%c" % chh
else:
outx += "."
outx += " | \n"
# Print remainder on last line
remn = lenx % 16 ; divi = lenx / 16
if remn:
outx += " "
for dd in range(remn):
outx += "%02x " % ord(strx[divi * 16 + dd])
outx += " " * ((16 - remn) * 3)
outx += " | "
for cc in range(remn):
chh = strx[divi * 16 + cc]
if isprint(chh):
outx += "%c" % chh
else:
outx += "."
outx += " " * ((16 - remn))
outx += " | \n"
return(outx)