Themis
Themis

Reputation: 569

Python clearing lru_cache every defined amount of time

I am making many redundant calls to an api, so I decided to utilize lru_cache. However, I also wanted to clear the cache every so often in case the response value changes for a given input. So as a solution I created my own decorator in order to clear the cache every given amount of time, but now my function api_call() always seems to return None no matter what. Here's my code:

def cache_maintainer(clear_time: int):
    """
    A function decorator that clears lru_cache clear_time seconds
    :param clear_time: In seconds, how often to clear cache (only checks when called)
    """
    def inner(func):
        def wrapper(*args, **kwargs):
            if hasattr(func, 'next_clear'):
                if time.time() > func.next_clear:
                    func.cache_clear()
                    func.next_clear = time.time() + clear_time
            else:
                func.next_clear = time.time() + clear_time

            func(*args, **kwargs)
        return wrapper
    return inner


@cache_maintainer(86400)  # clear cache every 1 day
@lru_cache(maxsize=1000)
def api_call(param):
    return param

print(api_call("test"))

I can't for the life of me figure out what I've done wrong

Upvotes: 3

Views: 2588

Answers (2)

Themis
Themis

Reputation: 569

Very simple mistake, took much too long to figure out. As Tim Peters mentioned, func() is called but the result is thrown away (face palm). All I needed to do was add a return where func() is called and it works as I expected. Here's the modified properly working code:

def cache_maintainer(clear_time: int):
    """
    A function decorator that clears lru_cache clear_time seconds
    :param clear_time: In seconds, how often to clear cache (only checks when called)
    """
    def inner(func):
        def wrapper(*args, **kwargs):
            if hasattr(func, 'next_clear'):
                if time.time() > func.next_clear:
                    func.cache_clear()
                    func.next_clear = time.time() + clear_time
            else:
                func.next_clear = time.time() + clear_time

            return func(*args, **kwargs)
        return wrapper
    return inner


@cache_maintainer(86400)  # clear cache every 1 day
@lru_cache(maxsize=1000)
def api_call(param):
    return param

print(api_call("test"))

Upvotes: 5

bigbounty
bigbounty

Reputation: 17368

This answer is using python package - cachetools

To install cachetools - pip install cachetools

from cachetools import TTLCache

cache = TTLCache(maxsize=5, ttl=100)
cache['dog'] = 'dog'
a = cache['dog'] # dog
... after 100 seconds...
cache['dog']
KeyError exception thrown

Upvotes: 1

Related Questions