我有一个用Python 3编写的模块,其中一个功能是使用将unicode字符转换为代码点(例如
ord(''
到127921)。 / p>
现在我需要转换此代码以使其适用于Python 2,但ord()
不能使用非ascii字符在Python 2上工作。
我尝试使用''.encode('utf8')
或''.encode('hex')
,但无济于事。
查看__futures__
包,它似乎没有帮助。
我在这里缺少什么?
答案 0 :(得分:1)
您无法以简单的方式执行此操作:检查ord
联机帮助页:https://docs.python.org/2/library/functions.html#ord:python2中仅支持UCS2(因此代码低于65536)。
注意:您应该在u
前加上unicode字符串。
你应该手动计算
to_decode = u''
code = ord(to_decode[0])
if code >= 0xd800 and code <= 0xdbff:
# we have surrogates
code = (code - 0xd800) * 1024 + (ord(to_decode[1]) - 0xdc00) + + 0x010000
ADDENDUM:为什么?:
原始Unicode设想16位编码就足够了(这解释了Han / Kana(中文/日文)和韩文特殊实现的合并)。这给出了从0到65535的代码点,通常编码为UCS2。 Python 2使用这种编码。
当注意到16位不够时,Unicode找到了一种使用更多位的方法:使用“代理”:使用两个“16位字符”(第一个“代码”中的10位,但在0xD800..0xDBFF,第二个“代码”中的10位放入0xDC00..0xDFFF,并添加65536(这最后一点确保没有双重方式来编码字符(并进一步扩展unicode范围)。
UTF-16是UCS2加上代理的解释(如Unicode中所指定)。但python2使用UCS2。如果您尝试使用len(to_decode)
,则会获得2
(两个代理代码点/ UCS2字符,而不是Python3中的1
代码点)。上面的代码,使用普通的ord
来获取代码点(参数为unicode
类型,而不是string
类型),但如果它发现第一个字符是代理,则将其翻译(没有额外的检查)。 https://en.wikipedia.org/wiki/UTF-16#U+10000_to_U+10FFFF解释了计算结果。注意:Unicode指定代理代码永远不会被分配为代码点,因此上面的函数对于普通的UCS2也应该是安全的。
你应该调整代码,扫描一个字符串(一些字符放在一个unicode
(作为python2类型)字符,一些字符放在两个字符中。
我建议尽可能使用Python3:他们修复了unicode而没有变通方法(因此容易出错且更复杂),就像在python2或其他语言中一样。