我想要检查一个字符串是否为ASCII编码。
我知道使用ord()
方法可以实现,但是当我尝试使用ord('é')
时,会出现TypeError: ord() expected a character, but string of length 2 found
的错误。根据ord()
方法的文档中的解释,这是由于我所使用的Python版本构建方式引起的。
是否有其他的方法可以进行检查?
我想要检查一个字符串是否为ASCII编码。
我知道使用ord()
方法可以实现,但是当我尝试使用ord('é')
时,会出现TypeError: ord() expected a character, but string of length 2 found
的错误。根据ord()
方法的文档中的解释,这是由于我所使用的Python版本构建方式引起的。
是否有其他的方法可以进行检查?
我认为你没有问对问题—
在Python中,字符串没有与'ascii'、utf-8或任何其他编码相对应的属性。您的字符串的来源(无论是从文件中读取还是从键盘输入等)可能已经将Unicode字符串编码为ASCII以生成您的字符串,但这就是您需要去寻找答案的地方。
也许你可以问的问题是:“这个字符串是通过将Unicode字符串编码为ASCII而得到的吗?”——你可以通过尝试回答这个问题:
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"
str
,在Python 3中为bytes
)。 - dotancohenstr
都需要先编码为Unicode。答案应该写在这里。 - alexiss.decode('ascii') if isinstance(s, bytes) else s.encode('ascii')
在 Python 3 中。OP的输入是一个字节串 'é'
(Python 2 语法,当时还没有发布 Python 3),因此 .decode()
是正确的。 - jfsstr
是一个字节串。使用.decode('ascii')
来查找所有字节是否在ASCII范围内是正确的。 - jfsdef is_ascii(s):
return all(ord(c) < 128 for c in s)
ord(c) < 128
比c <= "\x7F"
更易读和直观。 - Slater Victoroffdef 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
try: s.encode('ascii'); return True
except UnicodeEncodeError: return False
(与上面相似,但由于在Python 3中字符串是Unicode类型,所以需要编码)。但是,这种方法在Python 3中会在有代理项字符时产生错误(例如 isascii('\uD800')
会引发错误而不是返回False
)。 - Artyerall
一样高效。 - Endle_Zhenbo不再需要在字符串上进行繁琐/低效的ASCII检查,新的内置str
/bytes
/bytearray
方法 - .isascii()
将检查字符串是否为ASCII。
print("is this ascii?".isascii())
# True
"\x03".isascii()
也为True。文档说明这只是检查所有字符是否在128(0-127)的码点以下。如果你想避免控制字符,你需要使用:text.isascii() and text.isprintable()
。仅使用isprintable
也不够,因为它会将像¿这样的字符视为(正确的)可打印字符,但它不在ascii可打印部分内,所以如果你想要两者都检查,你需要同时检查。还有一个问题:空格被认为是可打印的,制表符和换行符则不是。 - LucVincent Marchetti的想法是正确的,但在Python 3中已经弃用了str.decode
。你可以使用str.encode
来进行相同的测试:
try:
mystring.encode('ascii')
except UnicodeEncodeError:
pass # string is not ascii
else:
pass # string is ascii
请注意您想要捕获的异常已经从UnicodeDecodeError
变成了UnicodeEncodeError
。
最近遇到了类似的问题 -供以后参考
import chardet
encoding = chardet.detect(string)
if encoding['encoding'] == 'ascii':
print 'string is in ascii'
你可以使用以下方式:
string_ascii = string.decode(encoding['encoding']).encode('ascii')
{'confidence': 0.99, 'encoding': 'EUC-JP'}
(但在这种情况下完全错误)。 - Suzana你的问题是不正确的,你看到的错误不是由于你构建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 "code points",它们本身表示字形或字符。 它可以是“带有重音符号的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 string
def isAscii(s):
for c in s:
if c not in string.ascii_letters:
return False
return True
我在尝试确定如何使用/编码/解码一串编码格式未知的字符串(以及如何转义/转换其中的特殊字符)时发现了这个问题。
我的第一步应该是检查字符串的类型-我没有意识到从类型(s)可以获得关于其格式的良好数据。 这个答案非常有帮助,找到了我的实际问题所在。
如果你在进行编码时遇到
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 263: ordinal not in range(128)
特别是当你在ENCODING时,确保你不要尝试unicode()一个已经是unicode的字符串-出于某种可怕的原因,你会遇到ascii编解码器错误。(另请参阅Python Kitchen recipe和Python 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')
'àéç'
from curses import ascii
def isascii(s):
return all(ascii.isascii(c) for c in s)
ord('é')
的错误,@florisla表示OP正在使用Python 2。 - wjandrea