[three]Bean
Cached function calls with expiration in python with shelve and decorator
Jun 08, 2011 | categories: python View CommentsCacheing with decorators is nice. Sometimes you don't want to use something super heavyweight, but just a little something you rolled on your own.
import time import random @scached(cache_file='shelvecache.db', expiry=datetime.timedelta(seconds=5)) def f1(foo, bar='baz'): """ Example of using the cache decorator """ print " ** starting in f1.. sleepy time" time.sleep(5) # The result of all my hard work result = random.random() print " ** woke up with", result return result if __name__ == '__main__': print f1('hai') # slow print f1('hai') # fast print f1(foo='hai') # fast print "okay.. sleeping on the outside" time.sleep(5) print f1('hai') # slow again print f1('hai') # fast again
Here's the code that provides the @scached decorator.
import datetime import decorator import shelve from hashlib import md5 def scached(cache_file, expiry): """ Decorator setup """ def scached_closure(func, *args, **kw): """ The actual decorator """ key = md5(':'.join([func.__name__, str(args), str(kw)])).hexdigest() d = shelve.open(cache_file) # Expire old data if we have to if key in d: if d[key]['expires_on'] < datetime.datetime.now(): del d[key] # Get new data if we have to if key not in d: data = func(*args, **kw) d[key] = { 'expires_on' : datetime.datetime.now() + expiry, 'data': data, } # Return what we got result = d[key]['data'] d.close() return result return decorator.decorator(scached_closure)
For extra cool points, combine the above with my post on shelve and context managers.