【问题标题】:Python 'shelve' that writes itself to disk after each operationPython“搁置”在每次操作后将自身写入磁盘
【发布时间】:2013-10-06 22:21:33
【问题描述】:

我正在用 Python 做一个项目,该项目涉及大量使用持久字典的交互工作。如果我不进行交互式开发,我可以使用 contextlib.closure 并且相当确信架子最终会被写入磁盘。但就目前而言,没有任何代码可以轻松地包含在“with”语句中。我宁愿不必相信自己在会话结束时调用我书架上的 close()。

涉及的数据量不大,每次操作后我都会很乐意将一个架子同步到磁盘。我发现自己为 shelve 编写了一个包装器,但我不是一个足够强大的 Python 程序员来识别我需要覆盖的正确的 dict 方法集。在我看来,如果我正在做的是一个好主意,那么它可能以前就已经做过了。处理此问题的典型正确方法是什么?

我要补充一点,我喜欢使用 shelve,因为它是一个简单的模块,而且它带有 Python。如果可能的话,我宁愿避免做一些需要(例如)拉入一个复杂的库来处理数据库的事情。

我正在使用带有 SP3 的 WinXP、通过 Anaconda 1.6.2(32 位)的 Python 2.7.5,并在 Spyder 中运行。通过查看支持我的书架的文件的修改时间,我可以知道在我调用同步或关闭之前,书架不会更新。

【问题讨论】:

  • 你可以自己做,因为shelve模块的源代码在Lib/Shelve.py
  • 也许您可以使用atexit 注册一个回调,在您退出会话时关闭货架。我没有使用过 Spyder,所以我不确定这是否可以在那里工作。
  • 我认为atexit 更有意义,或者看看writeback 关键字参数?实际上,每次修改都刷新到磁盘可能会带来巨大的 I/O Bound Overhead。
  • @g.d.d.c:由于磁盘写入可能会被缓存,因此 i/o 开销可能是可以接受的。另外OP说数据量小,每次修改后同步就OK了。

标签: python persistence shelve


【解决方案1】:

您可以做的是子类DbfilenameShelf 并覆盖__setitem____delitem__ 以在每次更改后自动同步。像这样的东西可能会起作用(未经测试):

from shelve import DbfilenameShelf

class AutoSyncShelf(DbfilenameShelf):
    # default to newer pickle protocol and writeback=True
    def __init__(self, filename, protocol=2, writeback=True):
        DbfilenameShelf.__init__(self, filename, protocol=protocol, writeback=writeback)
    def __setitem__(self, key, value):
        DbfilenameShelf.__setitem__(self, key, value)
        self.sync()
    def __delitem__(self, key):
        DbfilenameShelf.__delitem__(self, key)
        self.sync()

my_shelf = AutoSyncShelf("myshelf")

当然,我不能保证它的性能。

【讨论】:

  • @kuzzooroo:如果您可以阅读源代码(或者它的文档足够好),这是您可以做的另一件事。
  • 如果什么都不做,我认为没有必要重载__init__(),而是调用超类'__init__()...
  • 我认为默认使用较新的pickle 协议并启用writeback 会很方便,因此调用者不需要指定这些。因此__init__().
  • 啊,是的,确实——抱歉,很明显我错过了这些细节。我个人认为使用库的默认参数值或指出注释或文档字符串中的差异可能会更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-29
  • 2021-08-18
相关资源
最近更新 更多