Python returns 单个 Unicode 字符串的长度为 2

Python returns length of 2 for single Unicode character string

在 Python 2.7:

In [2]: utf8_str = '\xf0\x9f\x91\x8d'
In [3]: print(utf8_str)

In [4]: unicode_str = utf8_str.decode('utf-8')
In [5]: print(unicode_str)
 
In [6]: unicode_str
Out[6]: u'\U0001f44d'
In [7]: len(unicode_str)
Out[7]: 2

因为 unicode_str 只包含一个 unicode 代码点 (0x0001f44d),为什么 len(unicode_str) return 2 而不是 1?

您的 Python 二进制文件是使用 UCS-2 支持(narrow 构建)编译的,并且在内部 BMP(基本多语言平面)之外的任何内容都使用surrogate pair.

这意味着此类代码点在询问长度时显示为 2 个字符。

如果这很重要(./configure --enable-unicode=ucs4 将启用它),您必须重新编译 Python 二进制文件以使用 UCS-4,或者升级到 Python 3.3 或更新版本,其中 Python's Unicode support was overhauled 使用可变宽度的 Unicode 类型,根据包含的代码点的要求在 ASCII、UCS-2 和 UCS-4 之间切换。

在 Python 版本 2.7 和 3.0 - 3.2 上,您可以通过检查 sys.maxunicode value; 来检测您的构建类型。对于窄的 UCS-2 构建,它将是 2^16-1 == 65535 == 0xFFFF,对于宽的 UCS-4 构建,它将是 1114111 == 0x10FFFF。在 Python 3.3 及更高版本中,它始终设置为 1114111。

演示:

# Narrow build
$ bin/python -c 'import sys; print sys.maxunicode, len(u"\U0001f44d"), list(u"\U0001f44d")'
65535 2 [u'\ud83d', u'\udc4d']
# Wide build
$ python -c 'import sys; print sys.maxunicode, len(u"\U0001f44d"), list(u"\U0001f44d")'
1114111 1 [u'\U0001f44d']