0

我正在 python 中搜索一个对象存储,它允许我存储一个以tuples 作为键的字典。我已经尝试过shelveshove,一旦我通过我的字典,它们都会退出并出现错误。有没有提供这个的解决方案?

为了推,

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

4

2 回答 2

1

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 将接受元组作为键并将它们全部存储在底层架子中。

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

于 2015-07-22T15:24:13.143 回答
0

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

sep = '#!#!#!#'

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

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

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

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

Per heredict ,仅 Python 2.7 和更新版本支持这种直接理解语法,但 2.6 和更早版本有替代方案。

在您的情况下,由于您已经定义了字典,因此在与存储库交互时,您必须做一些 dict-fu 来热交换 -ified 哈希的当前tuple密钥,但这应该不会太难。strshelve

这种方法并非完全没有错误,但可以说可以使因sep与您的tuple-of-str键冲突而产生问题的可能性非常小。另外,请注意,这种方法仅在您的密钥严格 tuple为 s 的情况下才有效str

于 2015-07-24T15:07:31.500 回答