Python字符串的最大长度是多少?
如果不考虑环境的影响,Python字符串中理论上最多可以有多少个字符呢?
3 个回答
在64位系统上,CPython 3.10可以处理大约9亿亿个字符。
不过,这个数字只适用于你的字符串里全是ASCII字符。如果字符串里有其他字符,最大长度可能会更小,因为CPython处理字符串的方式不同:
- 如果你的字符串只包含ASCII字符(从
U+00
到U+7F
),那么最大长度是9,223,372,036,854,775,758个字符; - 如果你的字符串只包含ASCII字符和来自拉丁-1补充Unicode块的字符(从
U+80
到U+FF
),那么最大长度是9,223,372,036,854,775,734个字符; - 如果你的字符串只包含基本多语言平面中的字符(比如包含西里尔字母但没有表情符号,即从
U+0100
到U+FFFF
),那么最大长度是4,611,686,018,427,387,866个字符; - 如果你的字符串可能包含至少一个表情符号(也就是说,包含基本多语言平面以外的字符,即
U+10000
及以上),那么最大长度是2,305,843,009,213,693,932个字符。
在32位系统上,最大大约是20亿或5亿个字符。如果你不知道自己是用64位还是32位系统,或者这两者有什么区别,基本上可以认为你是在用64位系统。
Python的字符串是length-prefixed
,这意味着它们的长度受限于存储长度的整数大小和系统可用的内存。自从PEP 353以来,Python使用Py_ssize_t
作为存储容器长度的数据类型。Py_ssize_t
的大小与编译器的size_t
相同,但它是有符号的。在64位系统上,size_t
是64位。1位用于符号,这意味着你有63位用于实际数量,这样CPython字符串的最大大小不能超过2⁶³ - 1字节,大约是900万TB(8EiB)。如果我们按照2022年11月的价格(大约$2/GB)来算,这么多内存大约需要190亿美元。对于32位系统(现在已经很少见),最大是2³¹ - 1字节,约为2GiB。
CPython会根据字符串中最长字符所需的字节数来决定每个字符使用1、2或4个字节。例如,如果你的字符串是'aaaaaaaaa'
,那么每个a
只需要1个字节;但如果你的字符串是'你好'
,那么每个字符可能需要4个字节。使用1字节每个字符的字符串还会使用48或72字节的元数据,而使用2或4字节每个字符的字符串则会使用72字节的元数据。每个字符串的末尾还有一个额外的字符用于结束标志,所以空字符串实际上是49字节。
当你在CPython中使用PyUnicode_New(Py_ssize_t size, Py_UCS4 maxchar)
来分配字符串时,它会进行这样的检查:
/* Ensure we won't overflow the size. */
// [...]
if (size > ((PY_SSIZE_T_MAX - struct_size) / char_size - 1))
return PyErr_NoMemory();
/* Largest positive value of type Py_ssize_t. */
#define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1))
这实际上是将-1
转换为size_t
(这是C编译器定义的一种类型,在64位系统上是64位无符号整数),这会导致它回绕到最大值2⁶⁴-1,然后再右移1位(这样符号位为0
),最终变成2⁶³-1,并将其转换为Py_ssize_t
类型。
struct_size
是str
对象元数据的一点开销,可能是48或72,它在函数的早期部分被设置。
struct_size = sizeof(PyCompactUnicodeObject);
if (maxchar < 128) {
// [...]
struct_size = sizeof(PyASCIIObject);
}
而char_size
是1、2或4,所以我们有
>>> ((2**63 - 1) - 72) // 4 - 1
2305843009213693932
当然,Python字符串的实际限制可能还受到其他我不知道的Python部分的影响,但只要你能搞到9个艾字节的内存,至少应该能分配到这么大的新字符串。
我在一个叫做 x2iedn.16xlarge 的 EC2 实例上运行了这段代码,这个实例有2048 GiB(也就是2.2 TB)的内存。
>>> one_gigabyte = 1_000_000_000
>>> my_str = 'A' * (2000 * one_gigabyte)
虽然花了几分钟,但我成功在运行Ubuntu 22.04的Python 3.10上分配了一个2TB的字符串。
>>> import sys
>>> sys.getsizeof(my_str)
2000000000049
>>> my_str
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...
最后一行代码实际上会卡住,但它会打印出20亿个 A
字符。
如果你使用的是64位的Python安装,并且有64GB的内存,那么大约63GB的Python字符串是可以实现的,虽然速度可能不是最快的。如果你能把内存升级到超过64GB,那么你可以使用的最大字符串长度也会相应增加。(不过我不建议你依赖虚拟内存来大幅度扩展这个限制,否则运行速度会变得非常慢;-)。
而如果你使用的是32位的Python安装,那么你在应用程序中能使用的总内存大约只有2到3GB(具体取决于操作系统和配置),所以你能使用的最长字符串会比64位安装和大内存情况下要小得多。