Kulu
Kulu

Reputation: 164

How to disable functools @lru_cache when developing locally

How do you disable caching when working with pythons functools? We have a boolean setting where you can disable the cache. This is for working locally.

I thought something like this:

@lru_cache(disable=settings.development_mode)

But there is no setting like that. Am I missing something? How are people doing this?

Upvotes: 2

Views: 132

Answers (4)

selle
selle

Reputation: 982

lru_cache exposes a few functions on the cached function. E.g. cache_info(), cache_clear(), and __wrapped__()

So here's two options:

  • Clear the cache after each execution or
  • Call the underlying function directly, bypassing the lru_cache

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() might also be useful for introspection of the cache status. E.g.

> foo.cache_info()
CacheInfo(hits=1, misses=1, maxsize=128, currsize=1)

Docs: https://docs.python.org/3/library/functools.html#functools.lru_cache

Upvotes: 0

D.lola
D.lola

Reputation: 2294

If you want to disable caching conditionally while using functools.lru_cache, you need to manage this manually, You need a decorator that can conditionally apply lru_cache based on your settings

I am using the docs as the guide docsOnFunctools

Quotes from docs:

If maxsize is set to None, the LRU feature is disabled and the cache can grow without bound.If typed is set to true, function arguments of different types will be cached separately. If typed is false, the implementation will usually regard them as equivalent calls and only cache a single result. (Some types such as str and int may be cached separately even when typed is 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

Then you can apply it to your code

# 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)

Upvotes: 2

blhsing
blhsing

Reputation: 107015

You can apply the decorator conditionally instead:

def f(x):
    return 2 * x

if not settings.development_mode:
    f = lru_cache(f)

Upvotes: 0

Marc
Marc

Reputation: 1629

You could give a maxsize of 0 (or negative for that matter), which will effectively turn off the cache since no values can enter the cache at all.

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

For your example this means that you could use a variable to set the size, and when you want to disable it set that variable to 0.

Upvotes: 1

Related Questions