Python字典有两个键与搁置

时间:2013-05-29 17:45:21

标签: python shelve

我想用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

这样可行,但似乎应该有更好的方法来充分利用搁置。有什么想法吗?

1 个答案:

答案 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)