在Python >= 3.2中将functools.lru_cache缓存存储到文件
我在使用Python 3.3中的@functools.lru_cache
,想把缓存保存到一个文件里,这样下次程序重启的时候就能恢复这些缓存。请问我该怎么做呢?
编辑 1 可能的解决方案:我们需要对任何可调用对象进行序列化
序列化__closure__
时遇到的问题:
_pickle.PicklingError: Can't pickle <class 'cell'>: attribute lookup builtins.cell failed
如果我尝试在没有它的情况下恢复这个函数,我会得到:
TypeError: arg 5 (closure) must be tuple
7 个回答
7
可以考虑使用 joblib.Memory 来实现持久化缓存,也就是把数据存储到硬盘上。
因为硬盘的容量非常大,所以其实不需要使用LRU缓存这种方式。
13
你可以使用我写的一个库,叫做 mezmorize
import random
from mezmorize import Cache
cache = Cache(CACHE_TYPE='filesystem', CACHE_DIR='cache')
@cache.memoize()
def add(a, b):
return a + b + random.randrange(0, 1000)
>>> add(2, 5)
727
>>> add(2, 5)
727
44
你不能用 lru_cache
来实现你想要的功能,因为它没有提供访问缓存的接口,而且将来可能会用C语言重写。如果你真的想保存缓存,就得用其他方法,这些方法能让你访问缓存。
自己写一个缓存其实很简单。比如:
from functools import wraps
def cached(func):
func.cache = {}
@wraps(func)
def wrapper(*args):
try:
return func.cache[args]
except KeyError:
func.cache[args] = result = func(*args)
return result
return wrapper
然后你可以把它当作装饰器来使用:
>>> @cached
... def fibonacci(n):
... if n < 2:
... return n
... return fibonacci(n-1) + fibonacci(n-2)
...
>>> fibonacci(100)
354224848179261915075L
并且可以获取 cache
:
>>> fibonacci.cache
{(32,): 2178309, (23,): 28657, ... }
接着你可以随意地对缓存进行序列化和反序列化,加载缓存可以用:
fibonacci.cache = pickle.load(cache_file_object)
我在python的bug跟踪系统里找到一个关于在 lru_cache
中添加序列化和反序列化功能的 功能请求,但这个请求没有被接受或实现。也许将来会有内置的支持来实现这些操作。