1

我需要使用一种复杂的 dict 并动态更改某些键的值。所以我尝试了以下方式,但遇到了大约 32GB RAM 的 MemoryError 。sys.getsizeof(d) 返回 393356,sys.getsizeof(d.items()) 是 50336。我是否以错误的方式使用了 python dict?谁能帮我 !?

d=nltk.defaultdict(lambda:nltk.defaultdict(float))
for myarticlewords in mywords:
    for i in myarticlewords:
        for j in myarticlewords:
            d[i][j]+=1.0   

回溯在“d[i][j]+=1.0”处停止

当我尝试:

dd=dict( (i,d[i].items() ) for i in d.keys() )

Traceback (most recent call last):
    File "<pyshell#34>", line 1, in <module>
    dd=dict( (i,d[i].items() ) for i in d.keys() )
   File "<pyshell#34>", line 1, in <genexpr>
   dd=dict( (i,d[i].items() ) for i in d.keys() )
MemoryError

谢谢!

4

1 回答 1

3

您似乎使用的是 32 位版本的 python。如果您正在运行 Windows,您可能已经达到了32 位程序的Windows 内存限制,即 2GB。

这与我根据一些有根据的猜测计算出的数字一致。首先,一些重要的事实:getsizeof只返回dict 本身的大小,而不是存储在其中的东西的大小。这适用于所有“容器”类型。此外,在添加了这么多项目之后,字典会以交错的方式增加它们的大小。

现在,当我存储一个包含大约 5500 到 21000 个项目的字典时,getsizeof返回 786712- 即393356 * 2. 我的 Python 版本是 64 位,因此这强烈建议我使用 32 位版本的 Python 存储 5500 到 21000 个项目。您正在使用nltk,这表明您在此处存储单词图。这意味着您至少有大约 5500 个单词。您正在为这些单词中的每一个存储第二个字典,这也是一个包含 5500 项的字典。所以你真正拥有的是393356 + 393356 * 5500字节,加上5500 * 20用于字存储的最少字节。总结一下:

>>> (393356 + 393356 * 5500 + 5500 * 20) / 1000000000.0
2.163961356

您正在尝试存储至少 2GB 的数据。所以简而言之,如果你想利用这 32 GB 的内存,你应该升级到 64 位版本的 Python。


我要补充一点,如果您担心性能,您可能只想使用pickle(or cPickle) 而不是shelve存储字典。shelve可能会更慢,即使你设置writeback=True.

>>> shelve_d = shelve.open('data', writeback=True)
>>> normal_d = {}
>>> def fill(d):
...    for i in xrange(100000):
...        d[str(i)] = i
...        
>>> %timeit fill(shelve_d)
1 loops, best of 3: 2.6 s per loop
>>> %timeit fill(normal_d)
10 loops, best of 3: 35.4 ms per loop

自然地,保存字典pickle也需要一些时间,但至少它不会减慢计算本身的速度。

于 2012-08-09T13:14:03.700 回答