如何检查Python中的字符串是否是ASCII?

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

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

还有别的办法吗?

269483 次浏览

您可以使用正则表达式库,它接受Posix标准[[:ASCII:]]定义。

我觉得你问的问题不对

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

也许你会问:“这个字符串是用ascii编码unicode字符串的结果吗?”——这个你可以回答 通过:< / p >
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"
def is_ascii(s):
return all(ord(c) < 128 for c in s)

这样做怎么样?

import string


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

你的问题不正确;你看到的错误不是你如何构建python的结果,而是混淆了字节字符串和unicode字符串。

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

而不是ord(u'é'),试试这个:

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

它告诉您“é”表示哪个代码点序列。它可能给你[233],也可能给你[101,770]。

而不是chr()来反转,有unichr():

>>> 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中的sting (str-type)是一系列字节。没有办法仅通过查看字符串就可以判断这一系列字节是否代表ascii字符串、ISO-8859-1等8位字符集的字符串或UTF-8或UTF-16或其他编码的字符串。

然而,如果你知道使用的编码,那么你可以decode str到一个unicode字符串,然后使用正则表达式(或循环)来检查它是否包含你所关心的范围之外的字符。

我使用以下方法来确定字符串是ascii还是unicode:

>> print 'test string'.__class__.__name__
str
>>> print u'test string'.__class__.__name__
unicode
>>>

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

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

最近遇到了类似的事情,供以后参考

import chardet


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

你可以用在:

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

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

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

如果你得到一个粗鲁而执着的

“ascii”编解码器无法解码263位置的0xc3字节:序号不在范围(128)

特别是当你正在进行ENCODING时,确保你没有尝试unicode()一个已经是unicode的字符串-由于某些可怕的原因,你会得到ascii编解码器错误。(请参阅Python厨房食谱Python文档教程,以更好地理解这有多可怕。)

最终我决定我想做的是:

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

在调试中也有帮助的是在我的文件中设置默认编码为utf-8(把它放在你的python文件的开头):

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

这允许您测试特殊字符('àéç'),而不必使用它们的unicode转义(u'\xe0\xe9\xe7')。

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

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

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

例如

def is_ascii(s):
try:
return all(ord(c) < 128 for c in s)
except TypeError:
return False

在Python 3中,我们可以将字符串编码为UTF-8,然后检查长度是否保持不变。如果是,那么原始字符串是ASCII。

def isascii(s):
"""Check if the characters in string s are in ASCII, U+0-U+7F."""
return len(s) == len(s.encode())

要检查,通过测试字符串:

>>> isascii("♥O◘♦♥O◘♦")
False
>>> isascii("Python")
True

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

from curses import ascii


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

Vincent Marchetti的想法是正确的,但str.decode在Python 3中已弃用。在Python 3中,你可以使用str.encode进行相同的测试:

try:
mystring.encode('ascii')
except UnicodeEncodeError:
pass  # string is not ascii
else:
pass  # string is ascii

注意,你想要捕获的异常也从UnicodeDecodeError变成了UnicodeEncodeError

import re


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

要包含一个空字符串作为ASCII,将+改为*

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

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

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

Python 3.7新增功能(bpo32677)

不再有讨厌/低效的ascii检查字符串,新的内置str/bytes/bytearray方法- .isascii()将检查字符串是否为ascii。

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