Python中使用Pickle的MemoryError

时间:2015-01-21 13:51:01

标签: python memory dictionary memory-leaks pickle

我正在处理一些数据,我已将结果存储在三个词典中,并且我已使用Pickle将它们保存到磁盘中。每个字典有500-1000MB。

现在我正在加载它们:

import pickle
with open('dict1.txt', "rb") as myFile:
    dict1 = pickle.load(myFile)

但是,在加载我得到的第一本字典时已经:

*** set a breakpoint in malloc_error_break to debug
python(3716,0xa08ed1d4) malloc: *** mach_vm_map(size=1048576) failed (error code=3)
*** error: can't allocate region securely
*** set a breakpoint in malloc_error_break to debug
Traceback (most recent call last):
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 858, in load
    dispatch[key](self)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1019, in load_empty_dictionary
    self.stack.append({})
MemoryError

如何解决这个问题?我的电脑有16GB的RAM,所以我觉得加载一个800MB的字典崩溃是不寻常的。我也发现不寻常的是在保存字典时没有问题。

此外,将来我计划处理更多数据,从而产生更大的词典(磁盘上为3-4GB),因此对于如何提高效率的任何建议表示赞赏。

3 个答案:

答案 0 :(得分:7)

如果您的词典中的数据是numpy数组,那么有些包(例如joblibklepto)可以使酸洗大型数组生效,因为kleptojoblib了解如何使用numpy.array的最小状态表示。如果您没有array数据,我的建议是使用klepto将字典条目存储在多个文件(而不是单个文件)或数据库中。

请参阅我对一个非常密切相关的问题https://stackoverflow.com/a/25244747/2379433的回答,如果你可以腌制到多个文件而不是单个文件,想要并行保存/加载数据,或者想要轻松实验使用存储格式和后端查看哪种方式最适合您的情况。另请参阅:https://stackoverflow.com/a/21948720/2379433了解其他可能的改进,以及https://stackoverflow.com/a/24471659/2379433

正如上面的链接所讨论的那样,您可以使用klepto - 这使您能够使用通用API轻松地将字典存储到磁盘或数据库。 klepto还允许您选择存储格式(picklejson等) - 而且HDF5(或SQL数据库)是另一个不错的选择,因为它允许并行访问。 klepto可以使用专门的pickle格式(如numpy)和压缩(如果您关心大小而不是访问数据的速度)。

klepto为您提供了使用“all-in-one”文件或“one-entry-per”文件存储字典的选项,还可以利用多处理或多线程 - 这意味着您可以保存和将字典项并行加载到后端或从后端加载。例如,请参阅以上链接。

答案 1 :(得分:4)

这是泡菜的固有问题, 适用于相当少量的 数据。字典的大小,当加载到内存中时, 比磁盘大很多倍。

加载100MB的pickle文件后,你可能会有 一本近1GB左右的字典。 网上有一些公式来计算开销,但我只能建议使用一些 像MySQL或PostgreSQL这样的数据库这样的数据库。

答案 2 :(得分:-2)

我认为您使用32位Python,并且限制为4GB。您应该使用64位而不是32位。我已经尝试过,我腌制的字典超过1.7GB,除了时间更长之外,我没有任何问题。