【问题标题】:Normalize composite/decomposable/variable-length characters (unicode/python3.4)规范化复合/可分解/可变长度字符(unicode/python3.4)
【发布时间】:2015-07-06 12:07:52
【问题描述】:

我偶然发现了http://mortoray.com/2013/11/27/the-string-type-is-broken/

令我恐惧的是......

print(len('noe\u0308l')) # returns 5 not 4

但是我发现 https://stackoverflow.com/a/14682498/1267259, Normalizing Unicode

from unicodedata import normalize
print(len(unicodedata.normalize('NFC','noe\u0308l'))) # returns 4

但是我该怎么处理薛定谔的猫呢?

print(len('????????')) # returns 4 not 2

(附带问题:在我的文本编辑器中,当我尝试保存时,我得到一个“utf-8 编解码器无法在位置 y 编码字符 x:不允许代理”但在命令提示符下我可以粘贴并运行带有这些字符的代码,我认为这是因为猫存在于不同的量子水平(SMP)上,但我该如何标准化它们?)

我还应该做些什么来确保所有字符都计为“1”?

【问题讨论】:

  • Python 3 的哪个特定版本? Unicode 处理发生了一两次变化。
  • 我使用的是 python 3.4.0。

标签: python python-3.x unicode python-unicode unicode-normalization


【解决方案1】:

为了在任何版本的 Python 上保持一致的代码点计数,编码为 UTF-32 并将字节数除以 4。

print(len(unicodedata.normalize('NFC','noe\u0308l').encode('utf-32le')) / 4)
print(len('\U0001f638\U0001f63e'.encode('utf-32le')) / 4)

【讨论】:

  • 但是 OP 使用的是 Python 3.4。这不是一个多语言问题。
  • @MartijnPieters 直到我离开我的答案才添加信息。如果你有更好的,那就去吧,因为在这一点上我很困惑。
【解决方案2】:

您的编辑器正在生成surrogate pairs,而不是实际的代码点,这就是您也收到该警告的原因。使用:

'\U0001f638\U0001f63e'

在不借助代理的情况下定义猫。

如果您确实有一个带有代理项的字符串,您可以通过 UTF-16 重新编码它们并允许使用 'surrogatepass' 错误处理程序对代理项进行编码:

>>> # \U0001f638 is \ud83d\ude38 when using UTF-16 surrogates
...
>>> '\ud83d\ude38'.encode('utf16', 'surrogatepass').decode('utf16')
'?'
>>> len(_)
1

来自Error Handlers documentation

'surrogateescape'
解码时,将字节替换为从U+DC80U+DCFF 的各个代理代码。当编码数据时使用'surrogateescape' 错误处理程序时,此代码将转回相同的字节。 (更多信息请参见PEP 383。)

【讨论】:

  • 事后看来,这太明显了。我会留下我的答案,以防以后对路人有用。
  • 谢谢,这确实处理了错误消息,不幸的是没有更多可爱的猫......虽然len('\U0001f638\U0001f63e') 现在返回 2。但是如何确保始终使用实际代码点或从不使用代理对?我是否需要以某种方式“规范化”字符串?我必须按照 Mark R 的建议去做吗?
  • @user1267259:您的正常数据输入来源是什么?如果它们是源代码中的字符串文字,我会使用\Uhhhhhhhh 转义序列,因为它可以为编辑器和编码配置省去很多麻烦。从文件或网络连接读取时,请使用正确的编解码器,通常不应在 Unicode 字符串值中使用代理项,而应仅在编码字节(它们所属的位置)中使用代理项。
  • 啊,我明白了。我的正常来源是一堆文本文件。我已经删除了非拉丁字符,但感觉复合字符可能会导致问题,所以我在谷歌上搜索,直到找到提到的文章。可变长度字符对我来说是新的,在我的恐慌中,我认为它们也可以以某种方式被认为是“分解的”(考虑到长度的结果)。我复制并粘贴了那些猫并没有帮助 :) 但如果我理解你的话:只要我正确加载/编码这些文件,代理就不应该有任何问题。我只需要 unicodedata.normalize (对不起,如果我是多余的)。
猜你喜欢
  • 2023-03-06
  • 2020-03-11
  • 2014-01-05
  • 2017-09-20
  • 2015-02-26
  • 2021-12-30
  • 2013-07-27
  • 2021-09-11
  • 2012-02-07
相关资源
最近更新 更多