簡體   English   中英

如何在asyncio循環中等待?

[英]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://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

然后,您可以使用awaitasyncio.waitasyncio.gather管理這些期貨。

  • 找到它真的不明顯。 我很難記住。

關於協同程序的文檔確實很清楚asyncio.wait的用途是什么。

  • 很難理解它的作用。 “等待”似乎說“我阻止”,但沒有清楚地傳達它阻止整個協程列表完成。

再次,請參閱文檔。

  • 你不能傳入一個生成器,它需要是一個真正的列表,我覺得在Python中真的不自然。

再次,請參閱文檔,特別是asyncio.as_completed

  • 如果我只有一個等待的怎么辦?

它應該仍然有效。

  • 如果我不想在我的任務上等待,並安排它們執行然后繼續我的其余代碼怎么辦?

然后你可以使用asyncio.ensure_furture 事實上, asyncio.waitasyncio.ensure_future (和其他一些邏輯)的便利函數。

  • 這種方式更加冗長扭曲和JS解決方案。

也許,但這不是一件壞事(從我的角度來看)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM