Python 中 Pickle 的内存错误

MemoryError with Pickle in Python

我正在处理一些数据并将结果存储在三个字典中,并使用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),因此欢迎任何有关如何提高效率的建议。

这是pickle固有的问题, 这是为了与相当少量的使用 数据。字典的大小,当加载到内存中时, 比磁盘大很多倍。

加载一个 100MB 的 pickle 文件后,你可能有 几乎 1GB 左右的字典。 网上有一些计算开销的公式,但我只能推荐使用一些 体面的数据库,如 MySQL 或 PostgreSQL,用于处理如此大量的数据。

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

请参阅我对一个非常密切相关的问题的回答 , if you are ok with pickling to several files instead of a single file, would like to save/load your data in parallel, or would like to easily experiment with a storage format and backend to see which works best for your case. Also see: for other potential improvements, and here too: 。

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

klepto 使您可以选择使用 "all-in-one" 文件或 "one-entry-per" 文件存储字典,还可以利用多处理或多线程——这意味着您可以保存和加载字典items to/from 后端并行。例如,请参阅上面的链接。

我假设您使用 32 位 Python,它有 4GB 的限制。您应该使用 64 位而不是 32 位。我已经试过了,我的pickled dict超过了1.7GB,除了时间变长,我没有遇到任何问题。