在每次迭代中保存pickle对象而不每次写入整个对象

1 投票
1 回答
2819 浏览
提问于 2025-04-18 16:00

我正在尝试将一个字典保存为一个pickle对象。

我的字典在一个很长的循环中每次迭代都会变得越来越大,我想知道是否可以在每次迭代时以一种高效的方式保存它,这样我就只保存每次迭代新增的键值对,而不是重新保存整个字典?

举个例子:

import pickle 

keys = [123,11,2,5]
values = [[10,3,2,1],[0],[1],[2,3],[3]]

for i in range(0,4):
    mydict[keys[i]] = values[i]
pickle.dump(mydict, open('/mydir/mydict.p','w'))

正如你在这里看到的,我在循环结束时保存了mydict,但理想情况下,我希望在循环的每个部分都以高效的方式保存它。

1 个回答

1

如果你想找一个可以把大量数据字典保存到硬盘或者数据库的工具,并且能够使用序列化和编码(比如代码库和哈希表),那么你可以看看 klepto

klepto 提供了一种字典的抽象方式,可以把数据写入数据库,包括把你的文件系统当作数据库来用(也就是说,可以把整个字典写入一个文件,或者把每个条目写入各自的文件)。对于大数据,我通常选择把字典表示为文件系统中的一个目录,每个条目对应一个文件。klepto 还提供了缓存算法,所以如果你使用文件系统作为字典的后端,可以通过使用内存缓存来避免一些速度上的损失。

>>> from klepto.archives import dir_archive
>>> d = {'a':1, 'b':2, 'c':map, 'd':None}
>>> # map a dict to a filesystem directory
>>> demo = dir_archive('demo', d, serialized=True) 
>>> demo['a']
1
>>> demo['c']
<built-in function map>
>>> demo          
dir_archive('demo', {'a': 1, 'c': <built-in function map>, 'b': 2, 'd': None}, cached=True)
>>> # is set to cache to memory, so use 'dump' to dump to the filesystem 
>>> demo.dump()
>>> del demo
>>> 
>>> demo = dir_archive('demo', {}, serialized=True)
>>> demo
dir_archive('demo', {}, cached=True)
>>> # demo is empty, load from disk
>>> demo.load()
>>> demo
dir_archive('demo', {'a': 1, 'c': <built-in function map>, 'b': 2, 'd': None}, cached=True)
>>> demo['c']
<built-in function map>
>>> 

klepto 还有其他选项,比如 compressionmemmode,可以用来定制你的数据存储方式(例如,压缩级别、内存映射模式等)。使用数据库(比如 MySQL 等)作为后端也同样简单(接口完全一样),而不是使用文件系统。你还可以关闭内存缓存,这样每次读写都会直接去存档,只需设置 cached=False

klepto 还允许你自定义编码,通过构建一个自定义的 keymap

>>> from klepto.keymaps import *
>>> 
>>> s = stringmap(encoding='hex_codec')
>>> x = [1,2,'3',min]
>>> s(x)
'285b312c20322c202733272c203c6275696c742d696e2066756e6374696f6e206d696e3e5d2c29'
>>> p = picklemap(serializer='dill')
>>> p(x)
'\x80\x02]q\x00(K\x01K\x02U\x013q\x01c__builtin__\nmin\nq\x02e\x85q\x03.'
>>> sp = s+p
>>> sp(x)
'\x80\x02UT28285b312c20322c202733272c203c6275696c742d696e2066756e6374696f6e206d696e3e5d2c292c29q\x00.' 

klepto 提供了很多缓存算法(比如 mrulrulfu 等),帮助你管理内存缓存,并会使用这些算法来处理存档的读取和写入。

你可以使用 cached=False 来完全关闭内存缓存,直接从硬盘或数据库读写。如果你的条目足够大,你可能会选择写入硬盘,把每个条目放在自己的文件里。这里有一个同时做这两件事的例子。

>>> from klepto.archives import dir_archive
>>> # does not hold entries in memory, each entry will be stored on disk
>>> demo = dir_archive('demo', {}, serialized=True, cached=False)
>>> demo['a'] = 10
>>> demo['b'] = 20
>>> demo['c'] = min
>>> demo['d'] = [1,2,3]

不过,这样通常会稍微降低执行速度……通常最好是指定一个最大值来保持在内存缓存中的数据量,并选择一个好的缓存算法。

你可以在这里获取 kleptohttps://github.com/uqfoundation

撰写回答