在为python字典分配和更新值时始终存在内存错误

时间:2012-08-09 12:37:39

标签: python dictionary error-handling

我需要使用复杂的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

谢谢!

1 个答案:

答案 0 :(得分:3)

您似乎使用的是32位版本的python。如果您正在运行Windows,那么对于32位程序,您可能会达到windows memory limit,即2GB。

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

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

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

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


我要补充一点,如果您担心性能问题,您可能只想使用pickle(或cPickle)而不是shelve来存储字典。即使您设置了shelvewriteback=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保存字典也需要一些时间,当然,至少它不会减慢计算本身的速度。