我使用Windows 7 64位和Python 2.7 32位在python控制台中得到以下输出:
>>> a = {}
>>> for k in xrange(1000000): a[k] = k
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
MemoryError
>>> len(a)
21846
>>> a[21846]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 21846
>>> a[21846] = 21846
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
MemoryError
为什么我不能添加超过21846项dict?
这个号码的具体内容是什么(2 * 3 * 11 * 331)?
注意:我的内存比sys.getsizeof(a)== 393356
多得多答案 0 :(得分:6)
非常令人惊讶!关于21846,Python并没有什么特别之处。这里是32位Windows Vista与Python 2.7.5以及适度的3 GB RAM:
>>> a = {}
>>> for k in xrange(1000000): a[k] = k
...
>>> len(a)
1000000
也可以用1000万。但这是从一个新的控制台窗口开始的。也许你在向我们展示之前做了其他的事情,并留下了一些大型数据结构?按现代标准来看,21846很小; - )
这是发布到Python的错误跟踪器,在这里:http://bugs.python.org/issue19246
它被关闭为“不会修复”,因为同样的行为被一个简单的小纯C程序重现。也就是说,系统C的malloc()
和free()
是罪魁祸首,而且Python无法做到这一点。它似乎特定于Windows,使用Microsoft的C库。问题是堆碎片:在分配和释放许多不同大小的对象之后,系统malloc()
在被要求“大”的内存块时失败,尽管有大量可用的空闲字节。但它们不在一个连续的块中(至少不是系统中malloc()
认可的那个)。
发生了事情; - )
答案 1 :(得分:2)
这是您的环境约束,与Python词典无关。因此,您的问题的答案是:python字典可以保存尽可能多的环境。
答案 2 :(得分:2)
正如@Leifingson和@Tim所提到的,这种行为取决于之前完成的事情。为了说明内存消耗,我将使用以下示例:
Python 2.7 (r27:82525, Jul 4 2010, 09:01:59) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> a = {}
>>> for k in xrange(1000000): a['a' * k] = k
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
MemoryError
>>> len(a)
64036
如果我们采用摘要密钥长度:
>>> log(sum(xrange(64036)), 2)
30.93316861532543
我们接近整数溢出!
棘手的部分是:
>>> import sys
>>> sys.getsizeof(a)
1573004
sys.getsizeof
返回不同内容的大小,然后返回所有dict项。也许这是所有关键哈希的大小,我不知道。
完成后,
>>> a = {}
将释放所有2 Gb的已分配内存,但会将GC(我责备它)置于某种残缺状态。执行:
>>> for k in xrange(1000000): a[k] = k
将导致:
MemoryError
类似于问“魔法”号码:
>>> len(a)
87382