我在这里寻求帮助:
我有一个由 编写的函数,Python2.7
它需要很长时间才能返回结果,所以我想用它cache
来存储结果,每次调用该函数时,都应该返回缓存中的值,并且从函数返回的新结果应该异步更新缓存值. 这可能吗?
简而言之:
缓存函数结果。
每次调用函数,如果函数cache_key在缓存中,则返回缓存值,否则返回默认值。同时获取实时函数返回值,并更新缓存。
我试过了:
1.缓存工具
import time
from cachetools import cached, TTLCache
cache = TTLCache(maxsize=1, ttl=360)
@cached(cache)
def expensive_io():
time.sleep(300)
return 1.0
但是第一次expensive_io
调用该函数,还是要等300s,直到ttl超时才能更新缓存值。ttl 超时后,我必须再花 300 秒等待结果。
所以,我想知道也许我可以使用线程?:
2.穿线
from threading import Thread
import Queue
class asynchronous(object):
def __init__(self, func, maxsize=128, cache=OrderedDict()):
self.func = func
self.maxsize = maxsize
self.cache = cache
self.currsize = len(cache)
def getfuncthread(*args, **kwargs):
key = self.cache_key("{0}-{1}-{2}".format(self.func.__name__, str(*args), str(**kwargs)))
if self.currsize >= self.maxsize:
self.cache.popitem(False)
if not self.cache:
self.cache[key] = func(*args, **kwargs)
self.queue.put(self.cache[key])
def returnthread(*args, **kwargs):
key = self.cache_key("{0}-{1}-{2}".format(self.func.__name__, str(*args), str(**kwargs)))
if key in self.cache:
return self.cache[key]
else:
return 2222
self.returnthread = returnthread
self.getfuncthread = getfuncthread
def cache_key(self, s):
return hashlib.sha224(s).hexdigest()
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
def start(self, *args, **kwargs):
self.queue = Queue()
thread1 = Thread(target=self.getfuncthread, args=args, kwargs=kwargs)
thread2 = Thread(target=self.returnthread, args=args, kwargs=kwargs)
thread1.start()
thread2.start()
return asynchronous.Result(self.queue, thread2)
class NotYetDoneException(Exception):
def __init__(self, message):
self.message = message
class Result(object):
def __init__(self, queue, thread):
self.queue = queue
self.thread = thread
def is_done(self):
return not self.thread.is_alive()
def get_result(self):
if not self.is_done():
raise asynchronous.NotYetDoneException('the call has not yet completed its task')
if not hasattr(self, 'result'):
self.result = self.queue.get()
return self.result
@asynchronous
def expensive_io(n):
time.sleep(300)
return n*n
if __name__ == '__main__':
# sample usage
import time
result1 = expensive_io.start(2)
result2 = expensive_io.start(2)
result3 = expensive_io.start(4)
try:
print "result1 {0}".format(result1.get_result())
print "result2 {0}".format(result2.get_result())
print "result3 {0}".format(result3.get_result())
except asynchronous.NotYetDoneException as ex:
print ex.message
我在想,异步装饰器中有两个线程:
returnThread
用于从缓存中返回值,如果cache_key在缓存中,如果没有,立即返回一个默认值。
getfuncthread
用于通过调用func获取函数值,并将其放入缓存和队列中。
这似乎合乎逻辑,但仍然不起作用。
3.异步
我可以使用asyncio
吗?但是python2.7不支持asyncio
,我找到trollius
包了。但是还是不知道怎么处理。
任何想法将不胜感激。