如何检查Python中的string是否是ASCII码?
我想检查一个string是否是ASCII码。
我知道ord()
,但是当我尝试ord('é')
,我有TypeError: ord() expected a character, but string of length 2 found
。 我明白这是由我build立Python的方式(正如ord()
的文档中所解释的 )引起的。
有另一种方法检查?
def is_ascii(s): return all(ord(c) < 128 for c in s)
我想你不是在问正确的问题 –
python中的string没有与“ascii”,utf-8或任何其他编码对应的属性。 你的string的来源(不pipe你是从文件中读取,还是从键盘input等等)都可能用ASCII编码了一个unicodestring来产生你的string,但这就是你需要去做答案的地方。
也许你可以问的问题是:“这个string是在ASCII码中编码unicodestring的结果吗? – 这可以通过尝试来回答:
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"
Python 3的方式:
isascii = lambda s: len(s) == len(s.encode())
最近进入这样的事情 – 供将来参考
import chardet encoding = chardet.detect(string) if encoding['encoding'] == 'ascii': print 'string is in ascii'
你可以使用它:
string_ascii = string.decode(encoding['encoding']).encode('ascii')
你的问题是不正确的; 你看到的错误不是你如何构buildpython的结果,而是字节串和unicodestring之间的混淆。
字节string(例如python语法中的“foo”或“bar”)是八位字节的序列; 数字从0-255。 Unicodestring(例如u“foo”或u'bar“)是unicode代码点的序列; 数字从0-1112064。 但是你似乎对字符é感兴趣,字符(在你的terminal)是一个多字节的序列,代表一个字符。
而不是ord(u'é')
,试试这个:
>>> [ord(x) for x in u'é']
这告诉你代码点“é”代表的序列。 它可能会给你[233],也可能给你[101,770]。
chr()
代替chr()
来反转这个:
>>> unichr(233) u'\xe9'
这个字符实际上可以表示为单个或多个unicode“代码点”,它们本身代表字形或字符。 它可以是“具有尖锐口音(即,代码点233)”或“e”(代码点101),随后是“对前一个字符的尖锐口音”(代码点770)。 因此,这个完全相同的字符可以表示为Python数据结构u'e\u0301'
或u'\u00e9'
。
大多数情况下,你不必关心这个问题,但是如果你迭代一个unicodestring,就会成为一个问题,因为迭代是通过代码点来工作的,而不是可分解的字符。 换句话说, len(u'e\u0301') == 2
和len(u'\u00e9') == 1
。 如果这对你很重要,你可以使用unicodedata.normalize
在合成和分解的表单之间进行转换。
通过指出每个特定术语是如何引用文本表示的不同部分,这比许多程序员意识到的要复杂得多,Unicode的术语表可以作为理解其中一些问题的有用指南。
这样做怎么样?
import string def isAscii(s): for c in s: if c not in string.ascii_letters: return False return True
我试图确定如何使用/编码/解码一个string,其编码我不确定(以及如何转义/转换该string中的特殊字符),我发现这个问题。
我的第一步应该是检查string的types – 我没有意识到我可以从types(s)获得有关其格式的好的数据。 这个答案是非常有帮助的,并得到了我的问题的真正根源。
如果你变得粗鲁和持久
UnicodeDecodeError:'ascii'编解码器无法解码位置263中的字节0xc3:序号不在范围内(128)
特别是当你编码时,确保你没有试图unicode()一个string已经是unicode – 由于一些可怕的原因,你得到ascii编解码器错误。 (另请参阅Python的厨房食谱 ,以及Python文档教程,以更好地理解这可能是多么可怕。)
最终我确定了我想要做的是:
escaped_string = unicode(original_string.encode('ascii','xmlcharrefreplace'))
在debugging中也有帮助的是把我的文件中的默认编码设置为utf-8(把它放在你的python文件的开头):
# -*- coding: utf-8 -*-
这允许你testing特殊字符('àéç'),而不必使用unicode转义(u'\ xe0 \ xe9 \ xe7')。
>>> specials='àéç' >>> specials.decode('latin-1').encode('ascii','xmlcharrefreplace') 'àéç'
Vincent Marchetti有正确的想法,但str.decode
在Python 3中已被弃用。在Python 3中,您可以使用str.encode
进行相同的testing:
try: mystring.encode('ascii') except UnicodeEncodeError: pass # string is not ascii else: pass # string is ascii
请注意,您要捕获的exception也已从UnicodeDecodeError
更改为UnicodeEncodeError
。
为了从Python 2.6(和Python 3.x)中改进Alexander的解决scheme,可以使用helper模块curses.ascii并使用curses.ascii.isascii()函数或其他各种方法: https ://docs.python.org/2.6/ 库/ curses.ascii.html
from curses import ascii def isascii(s): return all(ascii.isascii(c) for c in s)
您可以使用接受Posix标准[[:ASCII:]]定义的正则expression式库。
Python中的sting( str
type)是一系列字节。 没有办法通过查看string来判断这一系列字节是否代表asciistring,如ISO-8859-1这样的8位字符集中的string,还是使用UTF-8或UTF-16编码的string,或者其他什么。
但是,如果您知道使用的编码,那么您可以将str decode
为unicodestring,然后使用正则expression式(或循环)来检查它是否包含您所关注的范围之外的字符。
为了防止你的代码崩溃,你可能想使用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
import re def is_ascii(s): return bool(re.match(r'[\x00-\x7F]+$', s))
要将一个空string包含为ASCII,请将+
更改为*
。
就像@ RogerDahl的答案一样,但是通过否定字符类别并使用search而不是find_all
或match
来短路是更有效的。
>>> 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
我想像一个正则expression式是非常优化的。
我使用以下来确定string是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