Python有没有现成的磁盘缓存装饰器?

7 投票
2 回答
1524 浏览
提问于 2025-04-17 07:57

我一直在寻找一个Python模块,它能提供一个记忆化装饰器,具备以下功能:

  • 能把缓存存储在磁盘上,以便在后续的程序运行中重复使用。
  • 适用于任何可以被序列化的参数,尤其是numpy数组。
  • (额外功能)检查函数调用时参数是否被修改。

我找到了一些小的代码片段来完成这个任务,自己也能实现一个,但我更希望能找到一个已经成熟的包来做这个。我还发现了incpy,但它似乎不适用于标准的Python解释器。

理想情况下,我希望能有类似于functools.lru_cache的东西,加上磁盘缓存存储。有人能推荐一个合适的包吗?

2 个回答

2

我知道这个问题已经有两年了,而且这可能不算是一个“成熟”的装饰器,但……

这个内容其实很简单,你完全不需要担心只用那些成熟的代码。这个模块的文档链接到了源代码,因为它不仅自己有用,还可以作为示例代码。

那么,你需要添加什么呢?添加一个filename参数。在运行时,用pickle.load把文件名加载到cache中,如果失败就用{}。再添加一个cache_save函数,这个函数只需要在锁定状态下用pickle.save把缓存保存到文件里。把这个函数和现有的函数(比如cache_info等)一样,附加到wrapper上。

如果你想自动保存缓存,而不是让调用者自己去做,这也很简单;只要决定什么时候保存就行。你想到的任何选项——比如用atexit.register,或者添加一个save_every参数,让它每save_every次未命中时保存……这些都很容易实现。在这个回答中,我展示了这需要多么少的工作。或者你可以在GitHub上找到一个完整的可用版本(可以自定义,或者直接使用)。

你还可以用其他方法来扩展它——在cache_info中放一些与保存相关的统计信息(比如最后保存时间、从上次保存以来的命中和未命中次数……),或者在后台线程中复制缓存并保存,而不是直接保存等等。但我想不出有什么值得做的事情是难以实现的。

2

我不知道有没有那种可以处理所有事情的记忆化装饰器,但你可以看看 ZODB。这是一个基于 pickle 的持久化系统,提供了一些额外的功能,比如可以在对象不被使用时把它们从内存移动到磁盘,以及只保存那些被修改过的对象。

编辑:关于评论的后续说明。ZODB 默认不支持记忆化装饰器。不过,我觉得你可以:

  • 自己实现一个 持久化类
  • 在你需要的方法中使用记忆化装饰器(任何标准实现都应该可以,但可能需要修改一下,以确保 脏标记 被设置)

之后,如果你创建了这个类的对象并把它添加到 ZODB 数据库中,当你执行其中一个记忆化的方法时,这个对象会被标记为脏,并且在下一个事务提交操作时,修改的内容会被保存到数据库里。

撰写回答