Skip to content

Caching

Roberto Prevato edited this page Jul 18, 2022 · 3 revisions

lazy decorator

Wraps a function so that it is called up to once every max_seconds, by input arguments. Results are stored in a cache, by default a LRU cache of max size 500. To have a cache without size limit, use a dictionary as cache: @lazy(1, {}).

import os

from essentials.caching import lazy

# example: a function that caches results of `os.path.isfile` by path, up to 1 second
@lazy(1) 
def file_exists(file_path): 
    return os.path.isfile(file_path)

Note from example above: results from ipython %timeit:

In [87]: %timeit file_exists("~/projects/github/essentials/tests/test_caching.py")                                                                                                                                        
583 ns ± 11.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [88]: %timeit os.path.isfile("~/projects/github/essentials/tests/test_caching.py")                                                                                                                                     
1.9 µs ± 33.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Cache

Basic cache with LRU (least recently used) strategy:

from essentials.caching import Cache

# create a cache object with default maximum size (500)
cache = Cache()

# set item
cache['foo'] = 12

# get item
x = cache['foo']

# optionally, use typing annotation for values (to get help from linters):
cache_of_integers = Cache[int]()

cache_of_integers ['foo'] = 'foo'  # <-- mypy reports error here

ExpiringCache

A cache whose items can expire by a given function.

import time

from essentials.caching import ExpiringCache

# create a cache whose items expire after 0.1 seconds:
cache = ExpiringCache.with_max_age(0.1)
cache['foo'] = 'Foo'

time.sleep(0.2)

assert cache.get('foo') is None

cache['foo'] = 'Foo'

time.sleep(0.2)

assert 'foo' not in cache
Clone this wiki locally