【问题标题】:What is the max length of a Python string?Python 字符串的最大长度是多少?
【发布时间】:2010-12-16 22:19:24
【问题描述】:

如果是环境无关的,理论上一个Python字符串的最大字符数是多少?

【问题讨论】:

    标签: python string


    【解决方案1】:

    CPython 3.10 上 64 位系统上的 9 个 quintillion 字符。

    仅当您的字符串仅由 ASCII 字符组成时。由于 CPython 实现字符串的方式,最大长度可以更小,具体取决于字符串包含的字符:

    • 9,223,372,036,854,775,758 个字符,如果您的字符串只有 ASCII 字符(U+00U+7F)或
    • 9,223,372,036,854,775,734 个字符,如果您的字符串仅包含 ASCII 字符和 Latin-1 Supplement Unicode blockU+80U+FF)中的字符或
    • 4,611,686,018,427,387,866 个字符,如果您的字符串仅包含 Basic Multilingual Plane 中的字符(例如,如果它包含西里尔字母但没有表情符号,即 U+0100U+FFFF)或
    • 2,305,843,009,213,693,932 个字符,如果您的字符串可能包含至少一个表情符号(更正式地说,如果它可以包含字符 outside the Basic Multilingual Plane,即 U+10000 及以上)

    在 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)。如果我们 multiply 今天的价格约为 $4/GB 90 亿,那么这么多 RAM 将花费您大约 400 亿美元。在 32 位系统上(现在很少见),它是 2³¹ - 1 个字节或 2GiB。

    CPython 将使用每个字符 1、2 或 4 个字节,具体取决于它需要多少字节来编码字符串中的“最长”字符。例如,如果你有一个像'aaaaaaaaa' 这样的字符串,a 的每个需要 1 个字节来存储,但是如果你有一个像 'aaaaaaaaa?' 这样的字符串,那么所有 a 现在每个都需要 4 个字节.每个字符 1 个字节的字符串也将使用 48 或 72 个字节的元数据,每个字符 2 或 4 个字节的字符串将使用 72 个字节的元数据。每个字符串的末尾还有一个额外的字符for a terminating null,所以空字符串实际上是49个字节。

    当你在 CPython 中使用PyUnicode_New(Py_ssize_t size, Py_UCS4 maxchar) (see docs) 分配字符串时,它会执行this check

        /* 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 is

    /* Largest positive value of type Py_ssize_t. */
    #define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1))
    

    这是casting -1 into a size_t(C 编译器定义的类型,64 位系统上的 64 位无符号整数),这导致它回绕到它的最大可能值,2⁶⁴-1,然后 right shifts 它由1(因此符号位是0),这会导致它变为 2⁶³-1 并将其转换为 Py_ssize_t 类型。

    struct_size 只是 str 对象元数据的一点开销,无论是 48 还是 72,它都设置为 earlier in the function

        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。

    【讨论】:

      【解决方案2】:

      我在 EC2 实例上运行了这段代码。

      def create1k():
          s = ""
          for i in range(1024):
              s += '*'
          return s
      
      def create1m():
          s = ""
          x = create1k()
          for i in range(1024):
              s += x
          return s
      
      def create1g():
          s = ""
          x = create1m()
          for i in range(1024):
              s += x
          return s
      
      print("begin")
      s = ""
      x = create1g()
      for i in range(1024):
          s += x
          print(str(i) + "g ok")
          print(str(len(s)) + ' bytes')
      

      这是输出

      [ec2-user@ip-10-0-0-168 ~]$ time python hog.py 
      begin
      0g ok
      1073741824 bytes
      1g ok
      2147483648 bytes
      2g ok
      3221225472 bytes
      3g ok
      4294967296 bytes
      4g ok
      5368709120 bytes
      5g ok
      6442450944 bytes
      6g ok
      7516192768 bytes
      7g ok
      8589934592 bytes
      8g ok
      9663676416 bytes
      9g ok
      10737418240 bytes
      10g ok
      11811160064 bytes
      11g ok
      12884901888 bytes
      12g ok
      13958643712 bytes
      13g ok
      15032385536 bytes
      14g ok
      16106127360 bytes
      15g ok
      17179869184 bytes
      16g ok
      18253611008 bytes
      17g ok
      19327352832 bytes
      18g ok
      20401094656 bytes
      19g ok
      21474836480 bytes
      20g ok
      22548578304 bytes
      21g ok
      23622320128 bytes
      22g ok
      24696061952 bytes
      23g ok
      25769803776 bytes
      24g ok
      26843545600 bytes
      25g ok
      27917287424 bytes
      26g ok
      28991029248 bytes
      27g ok
      30064771072 bytes
      28g ok
      31138512896 bytes
      29g ok
      32212254720 bytes
      30g ok
      33285996544 bytes
      31g ok
      34359738368 bytes
      32g ok
      35433480192 bytes
      33g ok
      36507222016 bytes
      34g ok
      37580963840 bytes
      35g ok
      38654705664 bytes
      36g ok
      39728447488 bytes
      37g ok
      40802189312 bytes
      38g ok
      41875931136 bytes
      39g ok
      42949672960 bytes
      40g ok
      44023414784 bytes
      41g ok
      45097156608 bytes
      42g ok
      46170898432 bytes
      43g ok
      47244640256 bytes
      44g ok
      48318382080 bytes
      45g ok
      49392123904 bytes
      46g ok
      50465865728 bytes
      47g ok
      51539607552 bytes
      48g ok
      52613349376 bytes
      49g ok
      53687091200 bytes
      50g ok
      54760833024 bytes
      51g ok
      55834574848 bytes
      52g ok
      56908316672 bytes
      53g ok
      57982058496 bytes
      54g ok
      59055800320 bytes
      55g ok
      60129542144 bytes
      56g ok
      61203283968 bytes
      57g ok
      62277025792 bytes
      58g ok
      63350767616 bytes
      59g ok
      64424509440 bytes
      60g ok
      65498251264 bytes
      61g ok
      66571993088 bytes
      62g ok
      67645734912 bytes
      63g ok
      68719476736 bytes
      64g ok
      69793218560 bytes
      65g ok
      70866960384 bytes
      66g ok
      71940702208 bytes
      67g ok
      73014444032 bytes
      68g ok
      74088185856 bytes
      69g ok
      75161927680 bytes
      70g ok
      76235669504 bytes
      71g ok
      77309411328 bytes
      72g ok
      78383153152 bytes
      73g ok
      79456894976 bytes
      74g ok
      80530636800 bytes
      75g ok
      81604378624 bytes
      76g ok
      82678120448 bytes
      77g ok
      83751862272 bytes
      78g ok
      84825604096 bytes
      79g ok
      85899345920 bytes
      80g ok
      86973087744 bytes
      81g ok
      88046829568 bytes
      82g ok
      89120571392 bytes
      83g ok
      90194313216 bytes
      84g ok
      91268055040 bytes
      85g ok
      92341796864 bytes
      86g ok
      93415538688 bytes
      87g ok
      94489280512 bytes
      88g ok
      95563022336 bytes
      89g ok
      96636764160 bytes
      90g ok
      97710505984 bytes
      91g ok
      98784247808 bytes
      92g ok
      99857989632 bytes
      93g ok
      100931731456 bytes
      94g ok
      102005473280 bytes
      95g ok
      103079215104 bytes
      96g ok
      104152956928 bytes
      97g ok
      105226698752 bytes
      98g ok
      106300440576 bytes
      99g ok
      107374182400 bytes
      100g ok
      108447924224 bytes
      101g ok
      109521666048 bytes
      102g ok
      110595407872 bytes
      103g ok
      111669149696 bytes
      104g ok
      112742891520 bytes
      105g ok
      113816633344 bytes
      106g ok
      114890375168 bytes
      107g ok
      115964116992 bytes
      108g ok
      117037858816 bytes
      109g ok
      118111600640 bytes
      110g ok
      119185342464 bytes
      111g ok
      120259084288 bytes
      112g ok
      121332826112 bytes
      113g ok
      122406567936 bytes
      114g ok
      123480309760 bytes
      115g ok
      124554051584 bytes
      116g ok
      125627793408 bytes
      Traceback (most recent call last):
        File "hog.py", line 25, in <module>
          s += x
      MemoryError
      
      real    1m10.509s
      user    0m16.184s
      sys 0m54.320s
      

      116GB 后出现内存错误。

      [ec2-user@ip-10-0-0-168 ~]$ python --version
      Python 2.7.12
      
      [ec2-user@ip-10-0-0-168 ~]$ free -m
                   total       used       free     shared    buffers     cached
      Mem:        122953        430     122522          0         11        113
      -/+ buffers/cache:        304     122648
      Swap:            0          0          0
      

      在运行 64 位 Amazon Linux AMI 2016.09 的 EC2 r3.4xlarge 实例上测试

      简短的回答是:如果您有超过 100GB 的 RAM,那么一个 Python 字符串可能会占用这么多内存。

      【讨论】:

      • 感谢分享实验。现在任何人都可以在未来复制它以进行自己的研究。
      • 这太疯狂了,它展示了 Python 的可靠实现,例如在 Java 中,它提高到 2Gb(最大签名 int32)。 Python 可能使用 malloc,它使用 size_t,在 64 位系统上是 18 446 744 TB
      • @BenoîtP 查看代码后,它是size_t&gt;&gt;1,元数据的开销很小,所以只有一半。微不足道的内存分配工作并没有什么“疯狂”......
      • @Boris 我同意你的看法。但在字符串缓冲区大小方面,并非所有语言都是平等的。尤其是脚本语言。我所指的疯狂之处在于,有人可能有一天想要分配 9 223 372 TB 的连续内存。
      • 我敢肯定,如果经济可靠的话,今天有成千上万的公司愿意这样做。
      【解决方案3】:

      使用 64 位 Python 安装和(例如)64 GB 内存,大约 63 GB 的 Python 2 字符串应该是非常可行的(如果不是最大速度的话)。如果你能将你的记忆力升级到远不止这些(当然,这将花费你一条胳膊和一条腿),你的最大可行字符串应该会成比例地变长。 (我不建议依赖虚拟内存来扩展它,否则你的运行时会变得非常荒谬;-)。

      当然,对于典型的 32 位 Python 安装,您可以在应用程序中使用的总内存限制为 2 或 3 GB(取决于操作系统和配置),因此您可以使用的最长字符串将是比具有高得离谱的 RAM 的 64 位安装要小得多。

      【讨论】:

        猜你喜欢
        • 2011-12-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-13
        • 1970-01-01
        • 2022-01-19
        • 2010-10-23
        • 2016-09-11
        相关资源
        最近更新 更多