У меня есть следующий декоратор в моем сценарии:Python общего назначения кэширования декоратор
def cached_to_disk(func):
"""Save the results of the func to the directory specified in datadir."""
path = datadir + func.__name__
if not os.path.exists(path):
os.makedirs(path)
@wraps(func)
def cached_func(page):
fullpath = "{}/{}".format(path, page.url)
if os.path.isfile(fullpath):
with open(fullpath) as cached_file:
data = cached_file.read()
else:
data = func(page)
if data is not None:
with open(fullpath, "w") as cached_file:
cached_file.write(data)
return data
return cached_func
Он прекрасно работает. Однако теперь я хочу расширить его работу для любой функции. В некотором роде:
@wraps(func)
def cached_func(*args, **kwargs):
pass
Проблема, с которой я столкнулась, определяет, где сохранить кеш. Когда я работаю с собственными объектами страницы, я могу просто использовать (нормализованный) URL-адрес в качестве имени файла. Однако, когда func
может принимать произвольные параметры, не так ясно, как определить имя файла. Я думал об использовании args[0].__repr__
, но это не очень хорошая идея для функций с несколькими аргументами (например, download(site, page_on_the_site)
) или без каких-либо аргументов.
В идеале, я бы хотел, чтобы декоратор общего назначения продолжал работать точно так же для тех функций, которые он уже поддерживает.
Есть ли простой и надежный способ сделать что-то подобное?
Вы можете создать кэш-ключ с помощью хэширования позиционного и ключевого аргументов. Смотрите [Py2.6 + и Py3.0 + обратный путь LRU Cache Python 3.3] (http://code.activestate.com/recipes/578078-py26-and-py30-backport-of-python-33s- lru-cache /) для примера (строка 17). –