python 中允许元组作为键的对象存储

object storage in python that allow tuples as keys

我正在 python 中搜索对象存储,它允许我存储以 tuple 为键的字典。我已经尝试过 shelve and shove,当我通过我的字典时,它们都以错误退出。有没有解决方案可以提供这个?

全压,

from shove import Shove
data = Shove('file://tmp')
("a",) in data

它给了我 AttributeError: 'tuple' object has no attribute 'rstrip'。但前提是元组不在数据中。

from shove import Shove
data = Shove('file://tmp')
data[("a",)] = 2
("a",) in data

不会抛出错误。

搁置,

import shelve
d = shelve.open('tmp/test.db')
d[('a',)] = 2

给我 TypeError: dbm mappings have string indices only

shelve 是 Python 标准库中的一个模块。文档对此很清楚:架子中的值(不是键!)本质上可以是任意的 Python 对象——pickle 模块可以处理的任何东西……键是普通字符串

通过构造搁置将只接受字符串作为键。

根据 pypi 的文档,Shove 仍处于测试阶段,我看不到任何证据表明它支持除密钥字符串以外的任何内容(错误 object has no attribute 'rstrip' 让我们认为它不支持)。

如果我是你,我会坚持使用众所周知的 shelve,并用密钥序列化层包裹它。正如 Padraic Cunningham 所建议的那样,pickle 应该可以胜任。

这是一个(未经过广泛测试的)可能的实现:

class tuple_dict(collections.MutableMapping):
    class iterator(collections.Iterator):
        def __init__(self, d):
            self.it = d.udict.__iter__()
        def __iter__(self):
            return self
        def next(self):
            return pickle.loads(next(self.it))
    def __init__(self, udict):
        self.udict = udict
    def __getitem__(self, key):
        ukey = pickle.dumps(key)
        return self.udict[ukey]
    def __setitem__(self, key, value):
        ukey = pickle.dumps(key)
        self.udict[ukey] = value
    def __delitem__(self, key):
        ukey = pickle.dumps(key)
        del self.udict[ukey]
    def keys(self):
        return [ pickle.loads(key) for key in self.udict.keys() ]
    def __iter__(self):
        return self.iterator(self)
    def __len__(self):
        return len(self.udict)
    def __contains__(self, key):
        return pickle.dumps(key) in self.udict
    def sync(self):
        self.udict.sync()
    def close(self):
        self.udict.close()

你会这样使用它:

import shelve
underlying_d = shelve.open('tmp/test.db')
d = tuple_dict(underlying_d)

d 然后将接受元组作为键并将其全部存储在底层货架中。

注意:如果您以后想使用不同的持久化实现,假设该实现是一个映射(类似 class 的字典),您可以通过简单地更改关闭和同步来重用 tuple_dict方法(具体搁置),但其他实现需要什么。事实上,除了这两种方法 tuple_dict 只是包装了一个普通的 dict - 因此任何映射 class ...

不知道这有多 pythonic 但是...如何定义一个常量分隔符字符串作为您的键字符串中几乎不可能出现的东西:

sep = '#!#!#!#'

然后,当您需要从字符串元组中为 shelve 创建一个键时,只需 .join 将它们变成一个粗略的散列:

import shelve
d = shelve.open('tmp/test.db')
d[sep.join(('a',))] = 2

如果您需要从 shelve 存储库中包含的信息重新生成 tuple 密钥,这就像 .split:

一样简单
my_dict = { tuple(k.split(sep)): d[k] for k in d.keys() }

根据 here,这种直接的 dict 理解语法仅支持 Python 2.7 和更新版本,但是 2.6 和更早版本有替代方法。

在你的例子中,因为你已经定义了一个字典,你必须做一些 dict-fu 来热交换你当前的 tuple 键为 str-ified 哈希与 shelve 存储库交互,但这应该不会太难。

这种方法并非完全没有错误,但可以说可以使 sep 与您的 tuple-of-str 的碰撞引起问题的概率钥匙小得几乎没有。另外,请注意,只有当您的密钥是 strictly tuples of strs.

时,此方法才有效