Как отключить кеширование при работе с Python functools? У нас есть логическая настройка, позволяющая отключить кеш. Это для локальной работы.
Я подумал примерно так:
@lru_cache(disable=settings.development_mode)
Но такой настройки нет. Я что-то упускаю? Как люди это делают?
@deceze Хорошо, я понимаю. Но как протестировать изменения во время разработки в функции, имеющей этот декоратор? После первого вызова функция больше не будет вызываться.
Вы можете задать максимальный размер 0 (или отрицательный, если уж на то пошло), что фактически отключит кеш, поскольку никакие значения вообще не могут попасть в кеш.
import functools
@functools.lru_cache(maxsize=0)
def f(a):
print("entered the function in f")
@functools.lru_cache
def g(a):
print("entered the function in g")
f(1)
f(1) # -> will also show "entered the function in f", thus not using the cache
g(1)
g(1) # -> does not show anything, thus using the cache
Для вашего примера это означает, что вы можете использовать переменную для установки размера, а когда вы хотите отключить ее, установите для этой переменной значение 0.
Вместо этого вы можете применить декоратор условно:
def f(x):
return 2 * x
if not settings.development_mode:
f = lru_cache(f)
lru_cache предоставляет несколько функций для кэшированной функции.
Например. cache_info()
, cache_clear()
и __wrapped__()
Итак, здесь два варианта:
import random
@lru_cache
def foo():
return random.random()
def test_foo():
foo()
# Clear cache
foo.cache_clear()
# Call again
foo()
# Call underlying function, uncached
foo.__wrapped__()
cache_info()
также может быть полезен для анализа состояния кэша. Например.
> foo.cache_info()
CacheInfo(hits=1, misses=1, maxsize=128, currsize=1)
Документы: https://docs.python.org/3/library/functools.html#functools.lru_cache
Если вы хотите условно отключить кеширование при использовании functools.lru_cache,
, вам нужно сделать это вручную. Вам нужен декоратор, который может условно применять lru_cache на основе ваших настроек.
В качестве руководства я использую документацию docsOnFunctools
Цитаты из документов: Если для параметра maxsize установлено значение None, функция LRU отключена, и кеш может расти без ограничений. Если для параметра typed установлено значение true, аргументы функций разных типов будут кэшироваться отдельно. Если typed имеет значение false, реализация обычно будет рассматривать их как эквивалентные вызовы и кэшировать только один результат. (Некоторые типы, такие как str и int, могут кэшироваться отдельно, даже если типизировано значение false.)
from functools import lru_cache, wraps
def remove_lru_cache(maxsize=128, typed=False, enable_cache=True):
def decorator(func):
if enable_cache:
return lru_cache(maxsize=maxsize, typed=typed)(func)
return func
return decorator
Затем вы можете применить его к своему коду
# settings
your_settings = {
'dev_mode': True #set False to enable caching
}
@remove_lru_cache(maxsize=None, typed=False, enable_cache=not settings['dev_mode'])
def add(nums: List[int]) -> int:
return sum(nums)
Люди делают это?
lru_cache
— это то, что, вероятно, не следует отключать, оно безоговорочно должно быть частью вашего кода. У вас могут быть другие виды кешей, такие как HTTP-заголовки и т. д., которые имеют разные настройки в производстве и разработке. Но это ваш собственный код бизнес-логики, а не что-то интегрированное в Python.