如果你使用64位的Python安装程序,且有(比如)64 GB 的内存,则一个大约63GB大小的Python字符串应该是可行的,尽管可能不是最快的。如果你可以将内存升级到超过64GB,那么你的最大可行字符串长度应该会相应地增加。(我不建议依赖虚拟内存来扩展它太多,否则你的运行时间会变得非常长;-)。
对于典型的32位Python安装程序,你在应用程序中可以使用的总内存量受限于操作系统和配置等因素,大约只能达到2或3 GB左右,因此你可以使用的最长字符串要比64位安装和高内存数的情况下小得多。
我在一台x2iedn.16xlarge的EC2实例上运行了此代码,该实例具有2048 GiB (2.2 TB)的RAM。
>>> 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...
最后一行代码实际上会卡住,但它将打印出2万亿个A
。
在64位的CPython 3.10系统上,最多可以容纳9万亿个字符。
这仅适用于字符串仅由ASCII字符组成的情况。如果字符串包含其他字符,则最大长度可能会更小,这是由于CPython实现字符串的方式导致的:
U+00
到U+7F
),则最多可容纳9,223,372,036,854,775,758个字符。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个字符。Python字符串是以长度为前缀的,因此它们的长度受限于存储其长度的整数大小和系统上可用的内存量。自从PEP 353之后,Python使用Py_ssize_t
作为存储容器长度的数据类型。Py_ssize_t
被定义为与编译器的size_t
相同的大小,但是有符号。在64位系统上,size_t
为64。1个符号位表示您有63个实际数量的位,这意味着CPython字符串不能大于2⁶³-1字节或约9百万TB(8EiB)。如果我们乘以今天(2022年11月)的价格约为$2/GB的9十亿,这么多RAM将花费您约190亿美元。在32位系统上(现在很少见),它是2³¹-1字节或2GiB。
CPython将根据需要编码的“最长”字符所需的字节数,使用每个字符1、2或4个字节。例如,如果您有一个像'aaaaaaaaa'
这样的字符串,则a
每个字符需要1个字节来存储,但如果您有一个像'中文'
这样的字符串,则所有中文
字符现在将需要每个4个字节。每个字符1字节的字符串还将使用48或72个字节的元数据,而每个2或4字节的字符的字符串将占用72个字节的元数据。每个字符串还在末尾有一个终止空字符,因此空字符串实际上是49个字节。
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();
PY_SSIZE_T_MAX
是什么?
/* 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