LRU кеш на питоне жесткого диска
Я хочу иметь возможность декорировать функцию, как вы это сделали бы с functools.lru_cache, однако я хочу, чтобы результаты кэшировались на жестком диске, а не в памяти. Оглядываясь вокруг, я чувствую, что это решенная проблема, и мне было интересно, если кто-нибудь может указать мне правильное направление (или, по крайней мере, дать мне еще несколько ключевых слов, чтобы попробовать поискать в Google)
Я не знаю, поможет ли это или имеет значение, но функция вычисляет изображения из уникальных имен файлов.
1 ответ
Вот код для начала:
from pathlib import Path
import pickle
import hashlib
import os
class LRU_Cache:
def __init__(self, directory, original_function, maxsize=10):
self.directory = directory
self.original_function = original_function
self.maxsize = maxsize
try:
os.mkdir(directory)
except OSError:
pass
def __call__(self, *args):
filename = hashlib.sha1(pickle.dumps(args)).hexdigest()
fullname = os.path.join(self.directory, filename)
try:
with open(fullname, 'rb') as f:
value = pickle.load(f)
Path(fullname).touch()
return value
except FileNotFoundError:
pass
value = self.original_function(*args)
with open(fullname, 'wb') as f:
pickle.dump(value, f)
filenames = os.listdir(self.directory)
if len(filenames) <= self.maxsize:
return
fullnames = [os.path.join(self.directory, filename)
for filename in filenames]
oldest = min(fullnames, key=lambda fn: os.stat(fn).st_mtime)
os.remove(oldest)
Он использует хеши аргументов для создания уникального имени файла для каждого вызова функции. Возвращаемое функцией значение обрабатывается с использованием этого имени файла.
Обращения к кешу отключают сохраненный результат и обновляют время модификации файла.
Если каталог кеша превышает целевой размер, самый старый файл кеша удаляется.
Используйте это так:
def square(x):
print('!')
return x ** 2
sqr = LRU_Cache('square_cache', square, 10)
Теперь вызовите sqr как обычно, и результаты будут кэшированы на диск.