测试python字符串是否可打印

BCS*_*BCS 27 python string

我有一些代码从一个com-port中提取数据,我想在打印之前确保我得到的是一个可打印的字符串(即ASCII,可能是UTF-8).这样做有功能吗?我看了上半打的地方,没有任何看起来像我想要的东西.(字符串有可打印但我没有看到任何东西(在那里,或在字符串方法中)来检查一个字符串中的每个字符是否在另一个字符串中.

注意:控制字符不能用于我的目的.


编辑:我正在寻找单一功能,而不是自己动手解决方案:

我最终得到的是:

all(ord(c) < 127 and c in string.printable for c in input_str)
Run Code Online (Sandbox Code Playgroud)

Dav*_*ebb 47

正如您所说的那样,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
Run Code Online (Sandbox Code Playgroud)

您可以将两个字符串转换为集合 - 因此集合将包含字符串中的每个字符一次 - 并检查字符串创建的集合是否是可打印字符的子集:

>>> 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
Run Code Online (Sandbox Code Playgroud)

因此,总而言之,您可能希望这样做:

import string
printset = set(string.printable)
isprintable = set(yourstring).issubset(printset)
Run Code Online (Sandbox Code Playgroud)

  • "为什么这个问题没有python将其作为一个函数?":这个解决方案,以及其他类似的解决方案,都是内置python工具的简单组合.如果给它一个特殊的名称,并且每个其他有用但微不足道的功能也有一个名称,那么python命名空间将非常混乱.这个简短的组合与一些假设的`stringutil.stringisprintable(myvar)`一样可读,除了不需要维护那个额外的模块. (8认同)
  • 我有点希望不推出自己的解决方案.为什么heck没有python将此作为一个函数? (4认同)
  • 这是否处理超出ASCII的任何内容? (4认同)
  • 好吧,Python确实有isalpha,isdigit,isspace,isalnum,islower,isupper和istitle.它缺少的一个(与C相比)是iscntrl,isgraph,isprint,ispunct和isxdigit.鉴于C库已经实现了它们,假设Python也拥有它们并不奇怪. (4认同)

Ale*_*lli 6

try/ except似乎是最好的方式:

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

我不会依赖string.printable,可能认为"不可打印"的控制字符通常可以"打印"以用于终端控制目的(例如,在"着色"ANSI转义序列中,如果您的终端符合ANSI标准).但是,这当然取决于你想要检查这个的确切目的! - )

  • 亚历克斯,你建议的功能即使是微不足道的无法打印输入也会失败; 例如:`isprintable('\ 00\01\02\03')`→`True` - 除非我误解你的意图? (4认同)
  • string.printable定义明确."数字,字母,标点符号和空格的组合." Whitesapce OTOH稍微不那么:"在大多数系统中,这包括字符空格,制表符,换行符,返回页面,换页符和垂直制表符." (2认同)
  • @BCS,它基本上与C的旧的`isprint`宏相同,并且表现出完全相同的失败(没有控制序列/转义序列 - 但许多终端和打印机可以接受一些控制/转义序列用于美化目的,如着色,并且,根据应用程序的目的,从输出中禁止这些字符可能因此被证明是不明智的). (2认同)

tha*_*kis 6

在Python 3中,字符串有一个isprintable()方法:

>>> 'a, '.isprintable()
True
Run Code Online (Sandbox Code Playgroud)

对于 Python 2.7,请参阅David Webb 的回答

  • 令人困惑的是,“str.isprintable()”与“string.printable”具有不同的“可打印”概念(例如,前者不认为“\n”和“\t”是可打印的)。 (2认同)

Joh*_*udd 5

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

>>> # Unprintable
>>> s = 'test\x00'
>>> len(s)+2 == len(repr(s))
False
Run Code Online (Sandbox Code Playgroud)

  • 这有点太聪明了.你可能不应该这样做,但无论如何+1,因为它让我微笑. (8认同)
  • 它失败了`s ='a \nb'`. (5认同)
  • 甚至没有'\\'.repr('\\')="'\\\\'" (5认同)

zvo*_*one 5

这个 Python 3 字符串包含各种特殊字符:

s = 'abcd\x65\x66 äüöë\xf1 \u00a0\u00a1\u00a2 ?? \a\b\r\t\n\v\\ \231\x9a \u2640\u2642\uffff'
Run Code Online (Sandbox Code Playgroud)

如果您尝试在控制台中显示它(或使用repr),它可以很好地从该字符串中转义所有不可打印的字符:

>>> s
'abcdef äüöëñ \xa0¡¢ ?? \x07\x08\r\t\n\x0b\\ \x99\x9a ??\uffff'
Run Code Online (Sandbox Code Playgroud)

它足够聪明,可以将水平标签 ( \t)识别为可打印,但将垂直标签 ( \v)识别为不可打印(显示为\x0b而不是\v)。

每个其他不可打印的字符也显示为\xNN\uNNNNrepr. 因此,我们可以将其用作测试:

def is_printable(s):
    return not any(repr(ch).startswith("'\\x") or repr(ch).startswith("'\\u") for ch in s)
Run Code Online (Sandbox Code Playgroud)

可能会有一些边界字符,例如不间断的空格 ( \xa0) 在此处被视为不可打印。也许它不应该是,但是那些特殊的可以被硬编码。


聚苯乙烯

您可以这样做以仅从字符串中提取可打印的字符:

>>> ''.join(ch for ch in s if is_printable(ch))
'abcdef äüöëñ ¡¢ ?? \r\t\n\\  ??'
Run Code Online (Sandbox Code Playgroud)