如何不等待异步循环?

How to not await in a loop with asyncio?

这是一个玩具示例,使用 asyncio 和 aiohttp 从多个网站下载主页:

import asyncio
import aiohttp

sites = [
    "http://google.com",
    "http://reddit.com",
    "http://wikipedia.com",
    "http://afpy.org",
    "http://httpbin.org",
    "http://whosebug.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

但我不想等待。

在twisted中我能做到:

for site in sites:
    download(site)

并且如果我没有明确地 "yield" 或向返回的 Deferred 添加回调,它只是 运行s 而不会阻塞或抱怨。我无法访问结果,但在这种情况下我不需要它。

在 JS 中我可以做到:

site.forEarch(site){
    donwload(site)
}

同样,它不会阻止也不需要我做任何事情。

我找到了一种方法:

async def main(sites):
    await asyncio.wait([download(site) for site in sites])

但是:

有更好的方法吗?

为了将协程安排为任务,使用asyncio.ensure_future:

for site in sites:
    coro = download(site)
    future = asyncio.ensure_future(coro)

它取代了版本 3.4.4 中已弃用的函数 asyncio.async

然后您可以使用 awaitasyncio.wait or asyncio.gather.

管理这些期货
  • this is really not obvious to find it out. I it's hard to remember.

关于 coroutines does make it pretty clear what asyncio.wait 目的的文档是。

  • it's hard to understand what it does. "waits" seems to say "i block", but does not convey clearly it block for the entire list of coroutine to finish.

同样,请参阅文档。

  • you can't pass in a generator, it needs to be a real list, which i feels really unatural in Python.

同样,请参阅文档,特别是 asyncio.as_completed

  • what if I have only ONE awaitable ?

它应该仍然有效。

  • what if I don't want to wait at all on my tasks, and just schedule them for execution then carry on with the rest of my code ?

那你就可以使用asyncio.ensure_furture了。事实上,asyncio.wait 是围绕 asyncio.ensure_future(和其他一些逻辑)的 便利 函数。

  • it's way more verbose thant twisted and JS solution.

也许吧,但这不是坏事(从我的角度来看)。