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 как обычно, и результаты будут кэшированы на диск.

Другие вопросы по тегам