如何检查python中的字符串是否为ascii?

How to check if a string in Python is in ASCII?

我想检查一个字符串是否是ASCII格式。

我知道ord(),但是当我尝试ord('é')时,我有TypeError: ord() expected a character, but string of length 2 found。我知道这是由我构建python的方式引起的(如ord()的文档中所述)。

还有其他检查方法吗?


我觉得你问的问题不对--

python中的字符串没有对应于"ascii"、utf-8或任何其他编码的属性。字符串的来源(无论是从文件中读取,还是从键盘输入等)可能已经用ASCII编码了一个Unicode字符串来生成字符串,但这正是您需要回答的地方。

您可能会问:"这个字符串是用ASCII编码Unicode字符串的结果吗?"--你可以回答这个问题尝试:

1
2
3
4
5
6
try:
    mystring.decode('ascii')
except UnicodeDecodeError:
    print"it was not a ascii-encoded unicode string"
else:
    print"It may have been an ascii-encoded unicode string"


1
2
def is_ascii(s):
    return all(ord(c) < 128 for c in s)


Python 3路:

1
isascii = lambda s: len(s) == len(s.encode())


最近碰到这样的事-供将来参考

1
2
3
4
5
import chardet

encoding = chardet.detect(string)
if encoding['encoding'] == 'ascii':
    print 'string is in ascii'

可用于:

1
string_ascii = string.decode(encoding['encoding']).encode('ascii')


您的问题不正确;您看到的错误不是您如何构建Python的结果,而是字节字符串和Unicode字符串之间的混淆。

字节字符串(如python语法中的"foo"或"bar")是八位字节的序列;0-255之间的数字。Unicode字符串(例如U"foo"或U"bar")是Unicode码位的序列;0-1112064中的数字。但您似乎对字符_感兴趣,它(在您的终端中)是表示单个字符的多字节序列。

尝试以下方法,而不是使用ord(u'é')

1
>>> [ord(x) for x in u'é']

它告诉你代码点的序列"_"代表什么。它可以给你[233],也可以给你[101770]。

chr()相反,unichr()是:

1
2
>>> unichr(233)
u'\xe9'

这个字符实际上可以表示为一个或多个Unicode"代码点",它们本身可以表示图形或字符。它可以是"e,带有锐音符(即代码点233)",也可以是"e"(代码点101),后跟"前一个字符的锐音符"(代码点770)。因此,这个完全相同的字符可以表示为python数据结构u'e\u0301'u'\u00e9'

大多数情况下,您不必关心这个问题,但是如果您在一个Unicode字符串上迭代,这可能会成为一个问题,因为迭代是按代码点进行的,而不是按可分解字符进行的。换言之,len(u'e\u0301') == 2len(u'\u00e9') == 1。如果这对您很重要,可以使用unicodedata.normalize在组合形式和分解形式之间进行转换。

Unicode术语表是理解其中一些问题的有用指南,它指出了每个特定术语是如何引用文本表示的不同部分的,这比许多程序员认识到的要复杂得多。


python 3.7中的新功能(bpo32677)

不再对字符串进行烦人/低效的ASCII检查,新的内置str/bytes/bytearray方法-.isascii()将检查字符串是否为ASCII。

1
2
print("is this ascii?".isascii())
# True


文森特·马切蒂的想法是正确的,但是在python 3中,str.decode已经被否决了。在python 3中,可以使用str.encode进行相同的测试:

1
2
3
4
5
6
try:
    mystring.encode('ascii')
except UnicodeEncodeError:
    pass  # string is not ascii
else:
    pass  # string is ascii

注意,您希望捕获的异常也已从UnicodeDecodeError更改为UnicodeEncodeError


做这个怎么样?

1
2
3
4
5
6
7
import string

def isAscii(s):
    for c in s:
        if c not in string.ascii_letters:
            return False
    return True


我在确定如何使用/编码/解码我不确定其编码的字符串(以及如何转义/转换该字符串中的特殊字符)时发现了这个问题。

我的第一步应该是检查字符串的类型-我没有意识到在那里我可以从类型中获得关于其格式的好数据。这个答案很有帮助,并找到了我问题的真正根源。

如果你变得粗鲁和执著

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 263: ordinal not in range(128)

尤其是在编码时,请确保您没有尝试unicode()一个已经是unicode的字符串-由于一些可怕的原因,您会得到ascii编解码器错误。(另请参阅python kitchen菜谱和python docs教程,以更好地了解这有多可怕。)

最终我决定我要做的是:

1
escaped_string = unicode(original_string.encode('ascii','xmlcharrefreplace'))

调试的另一个帮助是将my文件中的默认编码设置为utf-8(将其放在python文件的开头):

1
# -*- coding: utf-8 -*-

允许您测试特殊字符("_?")不必使用它们的Unicode转义符(u'xe0xe9xe7')。

1
2
3
>>> specials='àé?'
>>> specials.decode('latin-1').encode('ascii','xmlcharrefreplace')
'&#224;&#233;&#231;'

要从python 2.6(以及python 3.x)改进Alexander的解决方案,可以使用helper模块curses.ascii并使用curses.ascii.isascii()函数或其他各种函数:https://docs.python.org/2.6/library/curses.ascii.html

1
2
3
4
from curses import ascii

def isascii(s):
    return all(ascii.isascii(c) for c in s)


您可以使用正则表达式库,该库接受POSIX标准[[:ascii:]]定义。


python中的sting(str类型)是一系列字节。从字符串来看,无法判断这一系列字节是否代表一个ASCII字符串、一个8位字符集(如ISO-8859-1)中的字符串、或是一个用UTF-8或UTF-16编码的字符串。

但是,如果您知道所使用的编码,那么您可以将str转换成unicode字符串,然后使用正则表达式(或循环)检查它是否包含超出您关心的范围的字符。


为了防止代码崩溃,您可能需要使用try-except来捕获TypeErrors

1
2
3
4
>>> ord("?")
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
TypeError: ord() expected a character, but string of length 2 found

例如

1
2
3
4
5
def is_ascii(s):
    try:
        return all(ord(c) < 128 for c in s)
    except TypeError:
        return False

1
2
3
4
import re

def is_ascii(s):
    return bool(re.match(r'[\x00-\x7F]+$', s))

要将空字符串包含为ASCII,请将+更改为*


就像@rogerdahl的答案一样,但是通过否定字符类并使用搜索而不是find_allmatch,短路更有效。

1
2
3
4
5
>>> import re
>>> re.search('[^\x00-\x7F]', 'Did you catch that \x00?') is not None
False
>>> re.search('[^\x00-\x7F]', 'Did you catch that \xFF?') is not None
True

我认为正则表达式对此进行了很好的优化。


我使用以下内容来确定字符串是ASCII还是Unicode:

1
2
3
4
5
>> print 'test string'.__class__.__name__
str
>>> print u'test string'.__class__.__name__
unicode
>>>

然后使用条件块定义函数:

1
2
3
4
def is_ascii(input):
    if input.__class__.__name__ =="str":
        return True
    return False