我需要使用复杂的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
谢谢!
答案 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
来存储字典。即使您设置了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
保存字典也需要一些时间,当然,至少它不会减慢计算本身的速度。