我正在使用aiohttp在python 3.4中发出一个简单的HTTP请求,如下所示:
response = yield from aiohttp.get(url)
应用程序一遍又一遍地请求相同的URL,所以我自然想要缓存它 . 我的第一次尝试是这样的:
@functools.lru_cache(maxsize=128)
def cached_request(url):
return aiohttp.get(url)
第一次调用 cached_request
工作正常,但在以后的调用中我最终使用 None
而不是响应对象 .
我对asyncio比较新,所以我尝试了很多 asyncio.coroutine
装饰器, yield from
和其他一些东西的组合,但似乎都没有 .
那么缓存协同程序如何工作?
7 回答
我自己写了一个简单的缓存装饰器:
这种工作方式 . 但是很多方面都可能得到改善 . 例如:如果在第一次调用返回之前第二次调用缓存函数,它将再次执行 .
也许有点晚了,但我已经开始了一个可能有用的新包装:https://github.com/argaen/aiocache . 我们随时欢迎您的贡献/评论 .
一个例子:
请注意,作为额外的,它可以使用Pickle序列化将任何python对象缓存到redis中 . 如果您只想使用内存,可以使用
SimpleMemoryCache
后端:) .要使用带有协同程序的
functools.lru_cache
,以下代码可以正常工作 .以下是线程安全的
我不熟悉aiohttp所以我不确定会发生什么会导致Nones被返回,但是lru_cache装饰器不能用于异步函数 .
我使用的装饰器基本上是一样的;请注意,它与上面的tobib的装饰器不同,它总是返回一个future或一个任务,而不是值:
我使用functools中的_make_key作为lru_cache,我猜它应该是私有的,所以最好把它复制一遍 .
lru装饰器的另一个变种,它缓存尚未完成的协同程序,对同一个键的并行请求非常有用:
我认为最简单的方法是使用aiohttp_cache(documentation)
并在代码中使用它:
这里存在一个流行的异步版
lru_cache
:async_lru