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

时间:2008-10-13 00:13:40

标签: python string unicode ascii

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

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

还有其他检查方法吗?

16 个答案:

答案 0 :(得分:241)

我认为你没有问正确的问题 -

python中的字符串没有与'ascii',utf-8或任何其他编码对应的属性。你的字符串的来源(无论你是从文件中读取,从键盘输入等)都可能在ascii中编码了一个unicode字符串来生成你的字符串,但这就是你需要回答的地方。

也许您可以问的问题是:“此字符串是否是在ascii中编码unicode字符串的结果?” - 你可以回答     通过尝试:

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 :(得分:150)

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

答案 2 :(得分:138)

Python 3方式:

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

要检查,请传递测试字符串:

str1 = "♥O◘♦♥O◘♦"
str2 = "Python"

print(isascii(str1)) -> will return False
print(isascii(str2)) -> will return True

答案 3 :(得分:20)

最近进入类似的事情 - 以供将来参考

import chardet

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

您可以使用:

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

答案 4 :(得分:17)

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

字节串(例如,python语法中的“foo”或“bar”)是八位字节序列;数字从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

在合成和分解的表单之间进行转换

The Unicode Glossary可以帮助理解其中的一些问题,指出每个特定术语如何引用文本表示的不同部分,这比许多程序员意识到的要复杂得多。 p>

答案 5 :(得分:17)

Python 3.7(bpo32677)的新功能

不再对字符串进行繁琐/低效的ascii检查,新的内置str / bytes / bytearray方法-.isascii()将检查字符串是否为ascii。< / p>

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

答案 6 :(得分:10)

这样做怎么样?

import string

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

答案 7 :(得分:10)

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

str.encode

请注意,您要捕获的异常也已从try: mystring.encode('ascii') except UnicodeEncodeError: pass # string is not ascii else: pass # string is ascii 更改为UnicodeDecodeError

答案 8 :(得分:9)

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

我的第一步应该是检查字符串的类型 - 我没有意识到我可以从类型获得关于其格式的良好数据。 This answer was very helpful and got to the real root of my issues.

如果你得到一个粗鲁和持久的

  

UnicodeDecodeError:'ascii'编解码器无法解码位置263中的字节0xc3:序数不在范围内(128)

特别是当你在ENCODING时,确保你没有尝试unicode()一个已经是unicode的字符串 - 由于一些可怕的原因,你得到ascii编解码器错误。 (另请参阅Python Kitchen recipePython docs教程,以便更好地了解这可能会有多糟糕。)

最终我确定我想要做的是:

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

答案 9 :(得分:4)

要从Python 2.6(以及Python 3.x)中改进Alexander的解决方案,您可以使用帮助程序模块curses.ascii并使用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)

答案 10 :(得分:2)

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

答案 11 :(得分:2)

Python中的sting(str - type)是一系列字节。只有通过查看字符串来判断这一系列字节是否代表ascii字符串,8位字符集(如ISO-8859-1中的字符串)或使用UTF编码的字符串(无法) 8或UTF-16或其他。

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

答案 12 :(得分:0)

为防止您的代码崩溃,您可能希望使用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

答案 13 :(得分:0)

+

要将空字符串包含为ASCII,请将*更改为{{1}}。

答案 14 :(得分:0)

喜欢@ RogerDahl的answer但是通过否定字符类并使用搜索而不是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

我认为正则表达式已针对此进行了优化。

答案 15 :(得分:-4)

我使用以下内容来确定字符串是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