这是一个玩具示例,使用asyncio和aiohttp从多个网站下载主页:
import asyncio import aiohttp sites = [ "http://google.com", "http://reddit.com", "http://wikipedia.com", "http://afpy.org", "http://httpbin.org", "http://stackoverflow.com", "http://reddit.com" ] async def main(sites): for site in sites: download(site) async def download(site): response = await client.get(site) content = await response.read() print(site, len(content)) loop = asyncio.get_event_loop() client = aiohttp.ClientSession(loop=loop) content = loop.run_until_complete(main(sites)) client.close()
如果我运行它,我得到:
RuntimeWarning: coroutine 'download' was never awaited
但我不想等待它.
在扭曲我可以做:
for site in sites: download(site)
如果我没有明确地"收益"或向返回的Deferred添加回调,它只会在没有阻塞或抱怨的情况下运行.我无法访问结果,但在这种情况下我不需要它.
在JS我可以这样做:
site.forEarch(site){ donwload(site) }
而且,它不会阻止,也不需要我的任何部分.
我找到了办法:
async def main(sites): await asyncio.wait([download(site) for site in sites])
但:
找到它真的不明显.我很难记住.
很难理解它的作用."等待"似乎说"我阻止",但没有清楚地传达它阻止整个协程列表完成.
你不能传入一个生成器,它需要是一个真正的列表,我觉得在Python中真的不自然.
如果我只有一个等待的怎么办?
如果我不想在我的任务上等待,并安排它们执行然后继续我的其余代码怎么办?
这种方式更加冗长扭曲和JS解决方案.
有更好的方法吗?
要将协程安排为任务,请使用asyncio.ensure_future:
for site in sites: coro = download(site) future = asyncio.ensure_future(coro)
它取代了版本3.4.4中已弃用的函数asyncio.async.
然后你就可以管理使用这些期货await
,asyncio.wait或asyncio.gather.