Jun
12
2009
Caching the result of a python function using memcached and decorators
sarcachem.py
import memcache, time HOST = "127.0.0.1" PORT = "11211" MC_CLIENT = memcache.Client(['%s:%s'%(HOST,PORT)], debug=0) class sarcachem: class helper: def __init__(self, outer, fun): self.outer = outer self.fun = fun def __call__(self, *args, **kwargs): # If cached value does not exist # 1. Check to see if it is locked # If it is, wait until it unlocks # If it is not, lock and calculate value, # unlock when finished # Return cached value key = "%s.%s->(%s,%s)"%(self.outer.salt, self.fun.func_name, repr(args), repr(kwargs)) key_lock = "00_locked_%s"%(key) if MC_CLIENT.get(key) is None: if not MC_CLIENT.get(key_lock): MC_CLIENT.set(key_lock,True) result = self.fun(*args, **kwargs) MC_CLIENT.set(key,result,time=self.outer.time) print "Storing: ", key, ": ", MC_CLIENT.get(key) MC_CLIENT.delete(key_lock) else: while True: time.sleep(1) if not MC_CLIENT.get(key_lock): break else: continue return MC_CLIENT.get(key) def __init__(self,time=3,salt="base"): """ In this function we set all our decorator's parameters """ self.time = time self.salt = salt def __call__(self, fun): return sarcachem.helper(self, fun)
And here is the way you can use it:
from sarcachem import sarcachem @sarcachem(10,__file__) def fib(number=0): # Suck my life into the CPUHOLE for i in range(0,100000): i+100; # END OF LIFE SUCKER if number==0: return 0 elif number==1: return 1 else: return int(fib(number-1)) + int(fib(number-2)) if __name__=="__main__": print fib(100), fib(29)