我想用shelve存储一本大字典。更具体地说,我所拥有的是字典词典,如矩阵:
dict[key1][key2] = value
键的数量约为5.000,这使得5.000x5.000元素的矩阵无法存储在我的4Gb内存中。出于这个原因,我认为搁置可能是一个很好的解决方案。
尽管如此,我还没有找到任何有关如何有效地建立字典词典的文档。
到目前为止,我所做的是使用shelve创建一个包含常规词典的字典:
def create_entry(key1,key2,value,shelf): # shelf is the opened shelve file
if key1 not in shelf: # first time we see this key, initialise it
shelf[key1]={}
# add the contents
shelf[key1][key2]=value
这样可行,但似乎应该有更好的方法来充分利用搁置。有什么想法吗?
答案 0 :(得分:2)
你的解决方案唯一真正的问题是一个架子通过腌制来存储值,因此每次将它们分页到磁盘时,每个二级dicts都必须进行pickle和unpickled,这可能会产生很大的性能成本。 (当然,每个二级词典都必须适合记忆,但这可能不是问题。)
如果这无关紧要,那你正在做的事情很好。但如果确实如此,还有另外两种选择。
您可以使用比搁置更复杂的数据库,并围绕它构建自己的包装器。
或者,更简单:只需使用带有对的单级dict作为键:
def create_entry(key1, key2, value, shelf):
shelf[(key1, key2)] = value
这样做的缺点是,如果你需要,例如,迭代key1
子字典中的所有键或值,你将不得不迭代整个架子。它并不完全复杂((key2 for key1, key2 in shelf if key1 == key)
),但速度会慢得多。
上面的代码实际上并不直接用于shelve
,因为密钥必须是字符串。但是有很简单的方法来包装它;就像shelve
pickle和unpickles值一样,你可以写一个包装器而不是字符串化和解析键 - 例如:
def _mapkey(self, key):
return ','.join(map(str, key))
def _unmapkey(self, key):
return tuple(map(int, key.split(',')))
def __getitem__(self, key):
return self.shelf[self._mapkey(key)]
def __iter__(self):
return map(self._unmapkey, self.shelf)
# etc.
为了提高效率,最好对shelve
进行分叉或子类化,这样您就可以为基础bytes
密钥生成dbm
,而不是生成str
所以shelve
可以对其进行编码。然后你可以这样做:
def _mapkey(self, key):
return struct.pack('>II', key)
def _unmapkey(self, key):
return struct.unpack('<II', key)