如何检查 Python 中的字符串是否为 ASCII?
- 2025-02-12 10:03:00
- admin 原创
- 45
问题描述:
我想检查一个字符串是否是 ASCII 格式。
我知道ord()
,但是当我尝试时ord('é')
,我有TypeError: ord() expected a character, but string of length 2 found
。我明白这是由我构建 Python 的方式引起的(如ord()
的文档中所述)。
还有其他方法可以检查吗?
解决方案 1:
我认为你问的问题不对——
python 中的字符串没有与 'ascii'、utf-8 或任何其他编码相对应的属性。字符串的来源(无论是从文件读取,还是从键盘输入等)可能已将 unicode 字符串编码为 ascii 以生成字符串,但这就是您需要寻找答案的地方。
也许您可能会问的问题是:“这个字符串是用 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"
解决方案 2:
def is_ascii(s):
return all(ord(c) < 128 for c in s)
解决方案 3:
Python 3.7 中的新功能(bpo32677)
不再需要对字符串进行繁琐/低效的 ascii 检查,新的内置str
/ bytes
/bytearray
方法 -.isascii()
将检查字符串是否为 ascii。
print("is this ascii?".isascii())
# True
解决方案 4:
在 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
解决方案 5:
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
。
解决方案 6:
您的问题不正确;您看到的错误不是由您构建 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 词汇表可以作为理解其中一些问题的有用指南,它指出每个特定术语如何指代文本表示的不同部分,而这比许多程序员意识到的要复杂得多。
解决方案 7:
最近遇到了类似的事情 - 以供将来参考
import chardet
encoding = chardet.detect(string)
if encoding['encoding'] == 'ascii':
print 'string is in ascii'
您可以将其与以下对象一起使用:
string_ascii = string.decode(encoding['encoding']).encode('ascii')
解决方案 8:
这样做怎么样?
import string
def isAscii(s):
for c in s:
if c not in string.ascii_letters:
return False
return True
解决方案 9:
我在尝试确定如何使用/编码/解码我不确定其编码的字符串(以及如何转义/转换该字符串中的特殊字符)时发现了这个问题。
我的第一步应该是检查字符串的类型——我没有意识到我可以从类型中获得有关其格式的良好数据。 这个答案非常有帮助,找到了我问题的真正根源。
如果你遇到一个粗鲁而执着的人
UnicodeDecodeError:'ascii'编解码器无法解码位置 263 中的字节 0xc3:序数不在范围内(128)
特别是在进行编码时,请确保您没有尝试对已经是unicode的字符串进行unicode() - 由于某些可怕的原因,您会收到ascii编解码器错误。(另请参阅Python Kitchen食谱和Python文档教程,以更好地了解这有多么糟糕。)
最终我决定我想做的事情是:
escaped_string = unicode(original_string.encode('ascii','xmlcharrefreplace'))
将文件中的默认编码设置为 utf-8(将其放在 python 文件的开头)也有助于调试:
# -*- coding: utf-8 -*-
这样您就可以测试特殊字符('àéç'),而不必使用其 Unicode 转义符(u'àéç')。
>>> specials='àéç'
>>> specials.decode('latin-1').encode('ascii','xmlcharrefreplace')
'àéç'
解决方案 10:
为了改进 Alexander 在 Python 2.6(以及 Python 3.x)中的解决方案,您可以使用辅助模块 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)
解决方案 11:
您可以使用接受 Posix 标准 [[:ASCII:]] 定义的正则表达式库。
解决方案 12:
Python 中的字符串 ( str
-type) 是一系列字节。仅从字符串来看,无法判断这一系列字节是代表 ASCII 字符串、8 位字符集(如 ISO-8859-1)的字符串,还是用 UTF-8 或 UTF-16 或其他编码的字符串。
但是如果您知道所使用的编码,那么您可以将decode
str 转换为 unicode 字符串,然后使用正则表达式(或循环)来检查它是否包含您所关注的范围之外的字符。
解决方案 13:
与@RogerDahl 的答案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
我想象正则表达式已经针对这一点进行了很好的优化。
解决方案 14:
import re
def is_ascii(s):
return bool(re.match(r'[x00-x7F]+$', s))
要将空字符串包含为 ASCII,请将 更改+
为*
。
解决方案 15:
为了防止代码崩溃,你可能需要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