我想检查一个字符串是否为 ASCII 格式。
我知道ord()
,但是当我尝试时ord('é')
,我知道了TypeError: ord() expected a character, but string of length 2 found
。我知道这是由我构建 Python 的方式引起的(如ord()
's documentation中所述)。
有没有其他方法可以检查?
我想检查一个字符串是否为 ASCII 格式。
我知道ord()
,但是当我尝试时ord('é')
,我知道了TypeError: ord() expected a character, but string of length 2 found
。我知道这是由我构建 Python 的方式引起的(如ord()
's documentation中所述)。
有没有其他方法可以检查?
我认为你没有问正确的问题——
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"
def is_ascii(s):
return all(ord(c) < 128 for c in s)
在 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
不再对字符串进行烦人/低效的 ascii 检查,新的内置str
//方法 -将检查字符串是否为 ascii。bytes
bytearray
.isascii()
print("is this ascii?".isascii())
# True
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
。
你的问题不正确;您看到的错误不是您如何构建 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') == 2
和len(u'\u00e9') == 1
。如果这对您很重要,您可以使用unicodedata.normalize
.
Unicode 词汇表可以成为理解其中一些问题的有用指南,它指出每个特定术语如何指代文本表示的不同部分,这比许多程序员意识到的要复杂得多。
最近遇到这样的事情 - 以供将来参考
import chardet
encoding = chardet.detect(string)
if encoding['encoding'] == 'ascii':
print 'string is in ascii'
您可以使用:
string_ascii = string.decode(encoding['encoding']).encode('ascii')
这样做怎么样?
import string
def isAscii(s):
for c in s:
if c not in string.ascii_letters:
return False
return True
我在尝试确定如何使用/编码/解码我不确定其编码的字符串(以及如何转义/转换该字符串中的特殊字符)时发现了这个问题。
我的第一步应该是检查字符串的类型——我没有意识到我可以从类型中获得关于其格式的良好数据。 这个答案非常有帮助,并找到了我问题的真正根源。
如果你变得粗鲁和执着
UnicodeDecodeError:“ascii”编解码器无法解码位置 263 中的字节 0xc3:序数不在范围内(128)
特别是当你编码时,确保你没有尝试 unicode() 一个已经是 unicode 的字符串——由于某些可怕的原因,你会得到 ascii 编解码器错误。(另请参阅Python Kitchen recipe和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')
'àéç'
要从 Python 2.6(和 Python 3.x)改进 Alexander 的解决方案,您可以使用辅助模块 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:]] 定义的正则表达式库。
Python 中的字符串 ( str
-type) 是一系列字节。无法仅通过查看字符串来判断这一系列字节是表示 ascii 字符串、8 位字符集中的字符串(如 ISO-8859-1)还是用 UTF-8 或 UTF-16 编码的字符串或其他字符串.
但是,如果您知道使用的编码,那么您可以decode
将 str 转换为 unicode 字符串,然后使用正则表达式(或循环)来检查它是否包含您关注的范围之外的字符。
就像@RogerDahl 的回答find_all
一样,但通过否定字符类并使用 search 而不是or来短路更有效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
我想正则表达式对此进行了很好的优化。
import re
def is_ascii(s):
return bool(re.match(r'[\x00-\x7F]+$', s))
+
要将空字符串包含为 ASCII,请将*
.
为了防止您的代码崩溃,您可能需要使用 atry-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
我使用以下内容来确定字符串是 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