为什么unicodedata不识别某些字符?
在Python 2.7中,unicodedata.name()
这个函数不能识别某些字符。
>>> from unicodedata import name
>>> name(u'\n')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: no such name
>>> name(u'a')
'LATIN SMALL LETTER A'
确实,Unicode中包含了字符\n
,它有一个名字,叫做“换行符”。
注意,使用unicodedata.lookup('LINE FEED')
和unicodedata.lookup(u'LINE FEED')
这两个方法都会出现KeyError: undefined character name
的错误。
1 个回答
19
unicodedata.name()
这个查找功能是基于标准中的 UnicodeData.txt 数据库 的第二列(Python 2.7 使用的是 Unicode 5.2.0)。
如果这个名字是以 <
开头的,就会被忽略。所有的控制字符,包括换行符,都属于这一类;在第一列中,除了 <control>
之外,没有其他名字:
000A;<control>;Cc;0;B;;;;;N;LINE FEED (LF);;;;
第十列是 旧版 的 Unicode 1.0 名称,根据标准,这个名字是不应该使用的。换句话说,\n
除了通用的 <control>
外,没有其他名字,而 Python 数据库会忽略这个名字(因为它不唯一)。
Python 3.3 增加了对 NameAliases.txt 的支持,这样你可以通过别名来查找名字;所以 lookup('LINE FEED')
、lookup('new line')
或 lookup('eol')
等等,都是指向 \n
。不过,unicodedata.name()
方法不支持别名,也无法支持(那它该选哪个呢?):
- 增加了对 Unicode 名称别名和命名序列的支持。现在
unicodedata.lookup()
和'\N{...}'
都可以解析名称别名,unicodedata.lookup()
也能解析命名序列。
总结一下:LINE FEED
不是 \n
的官方名称,它只是一个别名。从 Python 3.3 开始,你可以通过别名来查找字符。