Проверьте, является ли строка Python для печати - PullRequest
25 голосов
/ 03 сентября 2010

У меня есть некоторый код, который извлекает данные из com-порта, и я хочу убедиться, что то, что я получил, действительно является строкой для печати (то есть ASCII, может быть, UTF-8) перед печатью. Есть ли функция для этого? Первые полдюжины мест, которые я посмотрел, не имели ничего похожего на то, что я хочу. ( строка имеет печатаемый , но я ничего не видел (там, или в строковые методы ), чтобы проверить, находится ли каждый символ в одной строке в другой.

Примечание: управляющие символы не для печати для моих целей.


Редактировать: я искал / ищу единственную функцию, а не решение по собственной инициативе:

В результате я получил:

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

Ответы [ 8 ]

45 голосов
/ 03 сентября 2010

Как вы сказали, модуль 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)
5 голосов
/ 03 сентября 2010

try / except кажется лучшим способом:

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

Я бы не стал полагаться на string.printable, который может воспринимать «непечатные» управляющие символы, которые обычно можно «напечатать» для целей управления терминалом (например, в «цветовых» escape-последовательностях ANSI, если ваш терминал ANSI- совместимый). Но это, конечно, зависит от ваших точных целей, желающих это проверить! -)

4 голосов
/ 07 июня 2018

Эта строка 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) здесь рассматривается как непечатаемый. Может быть, и не должно быть, но эти специальные могут быть жестко закодированы.


приписка

Вы можете сделать это, чтобы извлечь из строки только печатаемые символы:

>>> ''.join(ch for ch in s if is_printable(ch))
'abcdef äüöëñ ¡¢ 漢字 \r\t\n\\  ♀♂'
4 голосов
/ 29 июля 2011
>>> # Printable
>>> s = 'test'
>>> len(s)+2 == len(repr(s))
True

>>> # Unprintable
>>> s = 'test\x00'
>>> len(s)+2 == len(repr(s))
False
1 голос
/ 19 июня 2019
# 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)
0 голосов
/ 19 июня 2019
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
0 голосов
/ 18 февраля 2019

Mine - решение для избавления от любого известного набора символов.это может помочь.

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

...

0 голосов
/ 05 июля 2018

Функция category из unicodedata модуля может удовлетворить ваши потребности.Например, вы можете использовать это, чтобы проверить, есть ли какие-либо управляющие символы в строке, в то же время разрешая символы не ASCII.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...