Skip to content Skip to sidebar Skip to footer

Is There A Way To Cache Python 3.5 Definitions Using A Time-to-live Decorator?

Currently, I use functools' lru_cache to handle my caching for the function. The problem is that the size of the cache never grows large enough to make use of the LRU (due to the f

Solution 1:

I don't know of a decorator, but you can keep track of the last time you got the page and update as needed. If this is a single-threaded app, it can be simple

_cached_page = ''
_cached_page_time = 0def get_page():
    global _cached_page, _cached_page_time
    now = time.time()
    # invalidate in 1 hourifnot _cached_page or now - _cached_page_time > 60 * 60:
        _cached_page = get_the_page_here()
        _cached_page_time = time.time()
    return _cached_page

You could also age the page with a timer in the background. You need to control access with a lock, but that makes the cache usable in a multithreaded program too.

_cached_page = ''
_cached_page_lock = threading.Lock()

def _invalidate_page():
    global _cached_page
    with _cached_page_lock:
        _cached_page = ''def get_page():
    global _cached_page
    with _cached_page_lock:
        ifnot _cached_page:
            _cached_page = get_the_page_here()
            # invalidate in 1 hour
            threading.Timer(60*60, _invalidate_page)
        return _cached_page

Finally, the server may include an Expires: ... field in the http header. Depending on how well the service was written, this would be a good reflection of how long the page can be cached.

Solution 2:

The functools.lru_cache function accepts a maxsize argument which saves the results up to the maxsize most recent calls.

You can check this by calling the cache_info attribute of your decorated function.

If you want to refresh your cache completely you should implement a cash object manually by counting the number of cache calls and resetting the cache whenever it hits the max size.

from functools import wraps


classMycache(object):
    def__init__(self, maxcount):
        self.count = 0
        self.maxcount = maxcount
        self.cache = {}

    def__call__(self, func):

        @wraps(func)defwrapped(*args):
            self.count += 1if self.count > self.maxcount:
                self.cache = {}
                self.count = 0
                result = self.cache[args] = func(*args)
            else:
                try:
                    result = self.cache[args]
                except KeyError:
                    result = self.cache[args] = func(*args)
            return result
        return wrapped

Demo:

@Mycache(3)defa(arg):
    print("arg is : {}".format(arg))
    return arg ** 2print(a(4))
print(a(4))
print(a(4))
print(a(4))
print(a(3))
print(a(4))

output:

arg is : 4161616
arg is : 416
arg is : 3916

Post a Comment for "Is There A Way To Cache Python 3.5 Definitions Using A Time-to-live Decorator?"