Almacene el caché en un archivo functools.lru_cache en Python>=3.2
functools partial (4)
Estoy usando @functools.lru_cache
en Python 3.3. Me gustaría guardar la memoria caché en un archivo para poder restaurarla cuando se reinicie el programa. ¿Cómo podría hacerlo?
Edición 1 Posible solución: Necesitamos encurtir cualquier tipo de llamada
Problema de decapado __closure__
:
_pickle.PicklingError: Can''t pickle <class ''cell''>: attribute lookup builtins.cell failed
Si intento restaurar la función sin ella, obtengo:
TypeError: arg 5 (closure) must be tuple
Considere el uso de joblib.Memory para el almacenamiento en caché persistente en el disco.
Dado que el disco es enorme, no hay necesidad de un esquema de almacenamiento en caché LRU.
No puede hacer lo que quiere usando lru_cache
, ya que no proporciona una API para acceder a la memoria caché, y podría reescribirse en C en futuras versiones. Si realmente desea guardar el caché, debe utilizar una solución diferente que le permita acceder al caché.
Es lo suficientemente simple como para escribir un caché a ti mismo. Por ejemplo:
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
Luego puedes aplicarlo como decorador:
>>> @cached
... def fibonacci(n):
... if n < 2:
... return n
... return fibonacci(n-1) + fibonacci(n-2)
...
>>> fibonacci(100)
354224848179261915075L
Y recuperar el cache
:
>>> fibonacci.cache
{(32,): 2178309, (23,): 28657, ... }
A continuación, puede encoger / deseleccionar el caché como desee y cargarlo con:
fibonacci.cache = pickle.load(cache_file_object)
Encontré una solicitud de función en el rastreador de problemas de Python para agregar volcados / cargas a lru_cache
, pero no fue aceptada / implementada. Tal vez en el futuro sea posible tener soporte integrado para estas operaciones a través de lru_cache
.
Puedes usar una biblioteca mía, 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
Se supone que no debe tocar nada dentro de la implementación del decorador, excepto la API pública, por lo que si desea cambiar su comportamiento, probablemente necesite copiar su implementación y agregar las funciones necesarias. Tenga en cuenta que la memoria caché se almacena actualmente como una lista circular doblemente vinculada, por lo que deberá tener cuidado al guardarla y cargarla.