Python有没有现成的磁盘缓存装饰器?
我一直在寻找一个Python模块,它能提供一个记忆化装饰器,具备以下功能:
- 能把缓存存储在磁盘上,以便在后续的程序运行中重复使用。
- 适用于任何可以被序列化的参数,尤其是numpy数组。
- (额外功能)检查函数调用时参数是否被修改。
我找到了一些小的代码片段来完成这个任务,自己也能实现一个,但我更希望能找到一个已经成熟的包来做这个。我还发现了incpy,但它似乎不适用于标准的Python解释器。
理想情况下,我希望能有类似于functools.lru_cache
的东西,加上磁盘缓存存储。有人能推荐一个合适的包吗?
2 个回答
我知道这个问题已经有两年了,而且这可能不算是一个“成熟”的装饰器,但……
这个内容其实很简单,你完全不需要担心只用那些成熟的代码。这个模块的文档链接到了源代码,因为它不仅自己有用,还可以作为示例代码。
那么,你需要添加什么呢?添加一个filename
参数。在运行时,用pickle.load
把文件名加载到cache
中,如果失败就用{}
。再添加一个cache_save
函数,这个函数只需要在锁定状态下用pickle.save
把缓存保存到文件里。把这个函数和现有的函数(比如cache_info
等)一样,附加到wrapper
上。
如果你想自动保存缓存,而不是让调用者自己去做,这也很简单;只要决定什么时候保存就行。你想到的任何选项——比如用atexit.register
,或者添加一个save_every
参数,让它每save_every
次未命中时保存……这些都很容易实现。在这个回答中,我展示了这需要多么少的工作。或者你可以在GitHub上找到一个完整的可用版本(可以自定义,或者直接使用)。
你还可以用其他方法来扩展它——在cache_info
中放一些与保存相关的统计信息(比如最后保存时间、从上次保存以来的命中和未命中次数……),或者在后台线程中复制缓存并保存,而不是直接保存等等。但我想不出有什么值得做的事情是难以实现的。
我不知道有没有那种可以处理所有事情的记忆化装饰器,但你可以看看 ZODB。这是一个基于 pickle
的持久化系统,提供了一些额外的功能,比如可以在对象不被使用时把它们从内存移动到磁盘,以及只保存那些被修改过的对象。
编辑:关于评论的后续说明。ZODB 默认不支持记忆化装饰器。不过,我觉得你可以:
之后,如果你创建了这个类的对象并把它添加到 ZODB 数据库中,当你执行其中一个记忆化的方法时,这个对象会被标记为脏,并且在下一个事务提交操作时,修改的内容会被保存到数据库里。