我需要使用一种复杂的字典并动态更改某些键的值。 所以我尝试了以下方法,但遇到了大约 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
谢谢!
最佳答案
您似乎使用的是 32 位版本的 python。如果您运行的是 Windows,您可能已经点击了 windows memory limit对于 32 位程序,为 2GB。
这与我根据一些有根据的猜测计算出的数字相符。首先,一些重要的事实:getsizeof
仅返回字典本身的大小,而不是存储在其中的内容的大小。所有“容器”类型都是如此。此外,在添加了如此多的项目后,词典的大小会以交错的方式增加。
现在,当我存储大约 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
(或 cPickle
)而不是 shelve
存储字典。即使您设置了 writeback=True,shelve
也可能会变慢。
>>> 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
保存字典自然也会花费一些时间,但至少它不会减慢计算本身。
关于python - 向 python 字典分配和更新值时总是出现内存错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11883634/