我注意到在Python 2.7.6安装上,这会中断. Ascii字符和“低”代码点(序数< 2 ^ 16)表现如前.但是高代码点(> = 2 ^ 16)表现得非常奇怪. Python2.7.6似乎将它们视为两个代码点.这是一个基础知识的测试用例:
### "good" machine,Python2.7.3$uname -a && echo $LANGlinux *** 3.2.0-60-virtual #91-Ubuntu SMP Wed Feb 19 04:13:28 UTC 2014 x86_64 x86_64 x86_64 GNU/linuxen_US.UTF-8$python2.7Python 2.7.3 (default,Feb 27 2014,19:58:35) [GCC 4.6.3] on linux2Type "help","copyright","credits" or "license" for more information.>>> utest = u'a\u0395\U0001f30e' # three chars: ascii,"low" codepoint,"high" codepoint>>> utest.__class__<type 'unicode'>>>> len(utest),hash(utest)(3,1453079728409075183)>>> List(utest) # split into List of single chars[u'a',u'\u0395',u'\U0001f30e']>>> utest[2] # trying to extract third char (high codepoint)u'\U0001f30e'>>> len(utest[2])1>>> "%x" % ord(utest[2])'1f30e'
这是预期的行为.我用三个字符初始化一个unicode字符串. Python说它是三个字符,它可以“解决”第三个字符,返回单个预期的高代码点.如果我得到该代码点的序数,我会得到与原始转义序列中相同的数字.
现在是Python 2.7.6
### "bad" machine,Python 2.7.6$uname -a && echo $LANGlinux *** 2.6.32-431.5.1.el6.x86_64 #1 SMP Wed Feb 12 00:41:43 UTC 2014 x86_64 x86_64 x86_64 GNU/linuxen_US.UTF-8$python2.7Python 2.7.6 (default,Jan 29 2014,20:05:36)[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2Type "help","credits" or "license" for more information.>>> utest = u'a\u0395\U0001f30e'>>> utest.__class__<type 'unicode'>>>> len(utest),hash(utest) # !!!(4,-2836525916470507760)
第一个差异:Python 2.7.6表示utest的长度为4.哈希值也不同.下一个惊喜:
>>> List(utest) # !!![u'a',u'\ud83c',u'\udf0e']
不仅长度表现得很奇怪,分裂成单个字符甚至更奇怪,因为高码点的两个“半”变成两个低码点,没有明显的数字关系 – 至少对我来说 – 对于原始码点.
通过序列索引来解决该代码点表现出相同的破坏:
>>> utest[2]u'\ud83c'
为了获得原始的高代码点,我现在必须使用两个字符的切片:
>>> utest[2:4]u'\U0001f30e'
但是,如果不是很明显,Python2.7.6仍然在内部将其视为两个代码点.我没办法从中得到一个序数.
>>> len(utest[2:4])2>>> "%x" % ord(utest[2:4])Traceback (most recent call last): file "<stdin>",line 1,in <module>TypeError: ord() expected a character,but string of length 2 found
那么该怎么办?我的代码取决于unicode字符串中的代码点的序数.如果一个代码点有时真的是两个代码点,那么我的序数就会变得毫无意义,而我的代码也无法执行它的功能.
这种行为有理由吗?这是故意改变吗?
是否有一些配置旋钮我可以在Python内部或系统级别恢复旧的行为?猴子补丁?我不知道在哪里看.
不幸的是,我甚至无法将其缩小到精确的次要版本.我们有很多2.7.3,一些2.7.1和几个2.7.6安装.否2.7.4 / 2.7.5.我只能说,我在任何2.7.3安装上都没有遇到过这个问题.
额外信息:将字符串编码为utf8会产生两个Python版本完全相同的响应(相同的字符,相同的长度,相同的哈希值).再次解码编码的utf8仍然会让我回到正方形1(即它不是解决方法,行为在unicode空间中仍然存在分歧).
解决方法 您正在体验所谓的“代理对”.这些只发生在 narrow builds的python上,其中代码点在内部存储为UTF-16.您可以通过检查sys.maxunicode来确认您拥有的构建(它将是2 ** 16 – 1).其他一些好的阅读是PEP 393,遗憾的是……对于python 3.3,不幸的是.
编辑:谷歌搜索解决方法. Full credit to @dan04.
def code_points(text): import struct utf32 = text.encode('UTF-32LE') return struct.unpack('<{}I'.format(len(utf32) // 4),utf32)>>> len(utest)4>>> len(code_points(utest))3
如果你只关心长度你可以做len(utest.encode(‘UTF-32LE’))// 4,但看起来你想做更多,所以也许上面的功能是有帮助的.
总结以上是内存溢出为你收集整理的Python 2.7.6将单个“高”unicode代码点拆分为两个全部内容,希望文章能够帮你解决Python 2.7.6将单个“高”unicode代码点拆分为两个所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)