Python字符串的最大长度是多少?

104
如果Python字符串是与环境无关的,那么在理论上,Python字符串的最大字符数是多少?
3个回答

126

如果你使用64位的Python安装程序,且有(比如)64 GB 的内存,则一个大约63GB大小的Python字符串应该是可行的,尽管可能不是最快的。如果你可以将内存升级到超过64GB,那么你的最大可行字符串长度应该会相应地增加。(我不建议依赖虚拟内存来扩展它太多,否则你的运行时间会变得非常长;-)。

对于典型的32位Python安装程序,你在应用程序中可以使用的总内存量受限于操作系统和配置等因素,大约只能达到2或3 GB左右,因此你可以使用的最长字符串要比64位安装和高内存数的情况下小得多。


80

我在一台x2iedn.16xlargeEC2实例上运行了此代码,该实例具有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


12

在64位的CPython 3.10系统上,最多可以容纳9万亿个字符。

这仅适用于字符串仅由ASCII字符组成的情况。如果字符串包含其他字符,则最大长度可能会更小,这是由于CPython实现字符串的方式导致的:

  • 如果您的字符串仅包含ASCII字符(U+00U+7F),则最多可容纳9,223,372,036,854,775,758个字符。
  • 如果您的字符串仅包含ASCII字符和Latin-1 Supplement Unicode blockU+80U+FF)中的字符,则最多可容纳9,223,372,036,854,775,734个字符。
  • 如果您的字符串仅包含Basic Multilingual Plane中的字符(例如,如果它包含Cyrillic字母但不包含表情符号,即U+0100U+FFFF),则最多可容纳4,611,686,018,427,387,866个字符。
  • 如果您的字符串可能包含至少一个表情符号(更正式地说,如果它可以包含Basic Multilingual Plane之外的字符,即U+10000及以上),则最多可容纳2,305,843,009,213,693,932个字符。
在32位系统中,大约可以容纳20亿或5亿个字符。如果您不确定自己正在使用64位还是32位系统,或者不知道这意味着什么,那么您可能正在使用64位系统。

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个字节。

当您在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();

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

当然,Python 字符串的实际限制可能受到我不知道的 Python 的其他部分的影响,但是假设您可以获得 9 EB 的 RAM,您应该至少能够分配一个新的字符串以达到那个大小。请注意,此翻译仅供参考,可能需要根据上下文进行微调。

还有一个重要的因素是进程的地址空间大小。显然,最强大的现代CPU可以寻址五十多位的地址空间。无论你花费多少,你都无法获得超过这个数量的字符串。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接