检查一个字符串是否仅包含ASCII字符?

16

如何在Python中检查字符串是否仅包含ASCII字符?类似于Ruby中的ascii_only?方法。

我希望能够判断从文件读取的特定数据是否为ASCII码。

4个回答

36

Python 3.7新增了一些方法可以达到你想要的效果:

strbytes以及bytearray支持新的isascii()方法,用于测试字符串或字节是否仅包含ASCII字符。


否则:

>>> all(ord(char) < 128 for char in 'string')
True
>>> all(ord(char) < 128 for char in 'строка')
False

另一个版本:

>>> def is_ascii(text):
    if isinstance(text, unicode):
        try:
            text.encode('ascii')
        except UnicodeEncodeError:
            return False
    else:
        try:
            text.decode('ascii')
        except UnicodeDecodeError:
            return False
    return True
... 
>>> is_ascii('text')
True
>>> is_ascii(u'text')
True
>>> is_ascii(u'text-строка')
False
>>> is_ascii('text-строка')
False
>>> is_ascii(u'text-строка'.encode('utf-8'))
False

我认为这将始终创建整个列表?它使用更多的内存,并且如果第一个字符是>0x80字符,则速度会变慢,因为它会一直迭代整个字符串(在大多数应用程序中并不太重要,但在某些应用程序中很重要)。 - Martin Tournoij
2
@Carpetsmoker >我认为这将始终创建整个列表?< 不,不会。all内部的表达式是一个生成器,逐个提供字符。 - warvariuc
哪个更快且时间复杂度更低?还是两者相同? - JavaSa
1
@JavaSa,时间复杂度应该是相同的。哪个更快 - 你需要测量。我怀疑对于更大的字符串,编码/解码版本更快 - 它是用C实现的。 - warvariuc
有没有办法利用 mypy (http://www.mypy-lang.org) 来静态类型检查类型提示的字符串字面量,将其转换为 byte 类型以支持这一努力(在 mypy 检查时),而不仅仅依赖于运行时方法(我理解这是这个答案中正在发生的事情 - 如果我误解了,请纠正我)? - Johnny Utahh

6
如果您有 Unicode 字符串,可以使用 "encode" 函数,然后捕获异常:
try:
    mynewstring = mystring.encode('ascii')
except UnicodeEncodeError:
    print("there are non-ascii characters in there")

如果您有字节,可以导入chardet模块并检查编码:

import chardet

# Get the encoding
enc = chardet.detect(mystring)['encoding']

你应该捕获你期望的 UnicodeDecodeError 错误,而不是基本的 Exception 类。考虑一下如果由于某种原因 chardet.detect 没有一个 encoding 键,或者 mystring 是一个 listint 会发生什么。 - Martin Tournoij

6
您也可以选择使用正则表达式来检查仅 ASCII 字符。 [\x00-\x7F] 可以匹配单个 ASCII 字符:
>>> OnlyAscii = lambda s: re.match('^[\x00-\x7F]+$', s) != None
>>> OnlyAscii('string')
True
>>> OnlyAscii('Tannh‰user')
False

0
一个解决你问题的方法是尝试使用特定编码对字符串进行编码。

例如:
'H€llø'.encode('utf-8')

这将会抛出以下错误:

Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 1: ordinal not in range(128)

现在你可以捕获"UnicodeDecodeError"来确定字符串不仅包含ASCII字符。
try:
    'H€llø'.encode('utf-8')
except UnicodeDecodeError:
    print 'This string contains more than just the ASCII characters.'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接