不同的Unicode字符串编码相同

时间:2017-12-13 11:32:45

标签: python python-2.7 unicode encoding utf-8

我有两个unicode字符串,即使在规范化后也不同。但是,当编码为UTF-8时,它们是相同的。我想了解他们是如何(也许也就是为什么)不同。

它们都是实体的标识符,并且查找失败,因为标识符是错误的,但是作为字节字符串它们是相同的,所以我想了解我们如何可能到达不同的unicode字符串(它们&# 39;已由不同的子系统处理)以及我如何判断它们实际上是相同的。

"\u8a92\u6089\u5bfd\u4267\ucdb7\u5727\u4039\U0002ae18\U00025314\u30c3"

"\u8a92\u6089\u5bfd\u4267\ucdb7\u5727\u4039\ud86b\ude18\ud854\udf14\u30c3"

这个问题似乎没有规范化。我意识到这个问题的元素是无法回答的,但我会很感激任何线索!

>>> a = u"\u8a92\u6089\u5bfd\u4267\ucdb7\u5727\u4039\ud86b\ude18\ud854\udf14\u30c3"
>>> b = u"\u8a92\u6089\u5bfd\u4267\ucdb7\u5727\u4039\U0002ae18\U00025314\u30c3"
>>> a == b
False
>>> import unicodedata
>>> unicodedata.normalize('NFKD', a) == unicodedata.normalize('NFKD', b)
False
>>> a.encode('UTF-8') == b.encode('UTF-8')
True

1 个答案:

答案 0 :(得分:0)

我不确定你是如何得到你的结果的。在Python 2.7中,您的ab Unicode字符串是相同的:

    >>> a = u"\u8a92\u6089\u5bfd\u4267\ucdb7\u5727\u4039\ud86b\ude18\ud854\udf14\u30c3"
    >>> b = u"\u8a92\u6089\u5bfd\u4267\ucdb7\u5727\u4039\U0002ae18\U00025314\u30c3"
    >>> a == b
    True
    >>> a
    u'\u8a92\u6089\u5bfd\u4267\ucdb7\u5727\u4039\U0002ae18\U00025314\u30c3'
    >>> b
    u'\u8a92\u6089\u5bfd\u4267\ucdb7\u5727\u4039\U0002ae18\U00025314\u30c3'

Python 2.7在内部使用UTF-16LE来存储Unicode字符串。使用代理(两个16位代码单元)存储U + FFFF以上的代码点。请注意即使输入不同,它们也会显示相同的内容。这两个字符串以相同的方式在内部进行解析和存储。另一个例子:

>>> s = u'\U00025314'
>>> len(s)
2
>>> hex(ord(s[0]))
'0xd854'
>>> hex(ord(s[1]))
'0xdf14'
>>> s = u'\ud854\udf14'
>>> s
u'\U00025314'

在Python 3.3+中,已经修复了leaky abstraction公开内部存储Unicode的实现细节:

>>> # python 3.3+
>>> s = '\U00025314'
>>> len(s)
1
>>> hex(ord(s[0]))
>>> hex(ord(s[0]))
'0x25314'
>>> s.encode('utf8')
b'\xf0\xa5\x8c\x94'

>>> s = '\ud854\udf14'
>>> s
'\ud854\udf14'
>>> s.encode('utf8')
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
UnicodeEncodeError: 'utf-8' codec can't encode characters in position 0-1: surrogates not allowed