Simple function caching and memoization with automatic cache key generation and versioning.
- Easy to use decorator implementation.
- Implicit generation and versioning of cache keys based on introspection of generated bytecode or source code. No need to develop your own versioning or cache key naming schemes.
- Generation of unique cache keys from hashed argument values, safe to use with
argument unpacking (
*args
,**kwargs
) and complex hashable types. - Supports in-process memoization out-of-the-box as well as more robust caches, since backends are API compliant with Django, Flask, and Werkzeug. It is also trivial to write your own cache backend if your implementation of choice is not already supported.
- All argument values must implement the
__hash__
method, and this method must be deterministic between interpreter restarts, etc. This makes it impossible to use lists or dictionaries as arguments to a cached function, unless you convert the values into a hashable type before calling the cache-wrapped function. - Some types (specifically, user defined class instances) are hashable, but not
deterministic (their hash value evaluates to their
id()
-- in other words, their memory address) which can at best result in cache misses, and at worst result in hash collisions and invalid results. Please take the time to understand the__hash__
implementation of argument types that may be passed to your cached functions, and perhaps consider writing your own decorator that implements type checking to increase safety. - Refactoring can result in different generated bytecode and source
modifications will result in a different hash values, even if the underlying
logic of the function is the same. For example, changing an
if
/else
statement to a ternary statement will appear as a new version of the function. - Introspection of both bytecode and source code is limited to the the cached function itself, and doesn't provide any versioning of external functions.
- Bytecode is not guaranteed to be the same between different interpreter versions or implementations (for example, Python 2.6 to 2.7, or CPython to PyPy.) In many cases the bytecode will be identical, but not always.
To install from the git repository:
pip install -e "git://github.com/tkaemming/autocache.git#egg=autocache"
from autocache import cached
from autocache.backends import SimpleCacheBackend
cache = SimpleCacheBackend()
@cached(backend=cache)
def expensive_function(x):
# code
from autocache import cached
from django.core.cache import cache
@cached(backend=cache)
def expensive_function(x):
# code
from autocache import cached
from werkzeug.contrib.cache import SimpleCache
cache = SimpleCache()
@cached(backend=cache)
def expensive_function(x):
# code
To pass additional keyword arguments to the set
function of the cache backend,
pass a dictionary to the set_kwargs
argument of the decorator.
@cached(backend=cache, set_kwargs={'timeout': 5 * 60})
def expensive_function(x):
# code
TODO
To implement your own cache backend, just create a class that either extends
autocache.backends.CacheBackend
or provides the same API.
# optionally add "-p /usr/local/bin/pypy " argument if you have
# pypy installed and want to use it
virtualenv --no-site-packages autocache
cd autocache
echo "export PIP_RESPECT_VIRTUALENV=true" >> bin/activate
source bin/activate
git clone git://github.com/tkaemming/autocache.git repo
cd repo
To run the test suite, run make test
in the repository directory.
Please generally follow PEP8 style if you are planning on submitting patches.
Before submitting a patch, please make sure that it passes both pyflakes tests
and PEP8 checks by running make check
.
MIT Licensed, see LICENSE
for the full text.
- Ted Kaemming: https://github.com/tkaemming
- Mike Tigas: https://github.com/mtigas