为什么将python的“ shelve”转换为“ dict”会占用大量内存?

poc*_*ese 4 python memory shelve ipython

我有一个很大的python搁置对象(磁盘上有6GB)。我希望能够将其移动到另一台机器上,并且由于架子不是便携式的,因此我想cPickle它。为此,我首先必须将其转换为字典。

出于某种原因,当我执行dict(myShelf)ipython进程时,它会增加高达32GB的内存(我的机器所有内存),然后似乎挂起(或可能需要很长时间)。

有人可以解释吗?也许提供了一种潜在的解决方法?

编辑:使用Python 2.7

Ste*_*sop 5

根据我的经验,我希望腌制比您到目前为止所做的更多。但是,创建dict托架中的每个键和值都一次将其加载到内存中时,您不应该假设因为托架的磁盘上有6GB内存,所以它只有6GB。例如:

>>> import sys, pickle
>>> sys.getsizeof(1)
24
>>> len(pickle.dumps(1))
4
>>> len(pickle.dumps(1, -1))
5
Run Code Online (Sandbox Code Playgroud)

因此,一个很小的整数int(在我的机器上)比Python 对象大5到6倍。

至于解决方法:您可以在一个文件中写入多个腌制对象。因此,请勿将存储架转换为dict,只需将一长串的键和值写入文件,然后在另一侧读取同样长的键和值序列以放入新存储架。这样,一次只需要一个键/值对在内存中。像这样:

写:

with open('myshelf.pkl', 'wb') as outfile:
    pickle.dump(len(myShelf), outfile)
    for p in myShelf.iteritems():
        pickle.dump(p, outfile)
Run Code Online (Sandbox Code Playgroud)

读:

with open('myshelf.pkl', 'rb') as infile:
    for _ in xrange(pickle.load(infile)):
        k, v = pickle.load(infile)
        myShelf[k] = v
Run Code Online (Sandbox Code Playgroud)

我认为您实际上不需要存储该长度,您可以继续读取直到pickle.load抛出异常,表明该文件已用完。