4

这就是我所做的,尝试为类似 dict 的数据库创建一个包装器,以及其他功能:

    class database(object):
        def __init__(self, name):
            self.name = name
            self.db = anydbm.open(name, 'c')

        def __getitem__(self, key):
            key = str(key)
            try:
                self.db = anydbm.open(self.name, 'w') 
            except Exception,e: 
                raise e
            else:
                return cPickle.loads(self.db[key])
            finally:  
                self.db.close()

        def __setitem__(self, key, value):
            key = str(key)
            value = cPickle.dumps(value)
            try:
                self.db = anydbm.open(self.name, 'w')
            except Exception,e:
                print e 
            else:
                self.db[key] = value
            finally:  
                self.db.close()

当我尝试在嵌套的 dict 中定义新键时,似乎 getitem 返回的是值而不是引用,因此在 setitem 之后最终没有修改定义。

>>> from database import database
>>> db = database('test')
>>> db['a'] = {'alpha':'aaa'}
>>> db['a']['alpha'] = 'bbb'
>>> print db
{'a': {'alpha': 'aaa'}} //The value is not modified
4

1 回答 1

2

好吧,您必须了解自己在做什么:

db['a'] = {'alpha':'aaa'}

相当于

db.__setitem__('a', {'alpha':'aaa'})

所以这会将字典转储到磁盘。但是,当您这样做时

db['a']['alpha'] = 'bbb'

你首先从磁盘加载字典

tmp = db.__getitem__('a') # except tmp is pushed on the stack

然后改变这个字典:

tmp['alpha'] = 'bbb'

这显然对转储到磁盘的数据没有影响,因为您的对象不再涉及。

要完成这项工作,您不能返回一个简单的 dict,而是需要另一个对象来跟踪更改并将它们写回磁盘。

顺便说一句,你正在写shelve。它有同样的问题:

由于 Python 语义,架子无法知道何时修改了可变的持久字典条目。默认情况下,修改的对象仅在分配到架子时才写入(参见示例)。如果可选的 writeback 参数设置为 True,则所有访问的条目也会缓存在内存中,并在 sync() 和 close() 上写回;这可以更方便地改变持久字典中的可变条目,但是,如果访问了许多条目,它会消耗大量内存用于缓存,并且由于所有访问的条目都被写回,它会使关闭操作非常慢(无法确定哪些访问的条目是可变的,也无法确定哪些条目实际上是突变的)。

于 2013-05-21T17:55:03.523 回答