【问题标题】:Iterating over asyncio coroutines/Tasks as soon as they are ready准备就绪后立即迭代 asyncio 协程/任务
【发布时间】:2017-06-10 18:34:38
【问题描述】:

我使用aiohttp 发起了一堆请求。有没有办法在每个请求完成后立即获得结果?

也许使用类似async for 的东西?还是 Python 3.6 异步生成器?

目前我await asyncio.gather(*requests)并在它们全部完成后处理它们。

【问题讨论】:

    标签: python python-asyncio


    【解决方案1】:

    asyncio 具有 as_completed 功能,可能满足您的需求。请注意,它返回常规迭代器,而不是异步。

    以下是使用示例:

    import asyncio
    
    
    async def test(i):
        await asyncio.sleep(i)
        return i
    
    
    async def main():
        fs = [
            test(1),
            test(2),
            test(3),
        ]
    
        for f in asyncio.as_completed(fs):
            i = await f  # Await for next result.
            print(i, 'done')
    
    
    
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    try:
        loop.run_until_complete(main())
    finally:
        loop.run_until_complete(loop.shutdown_asyncgens())
        loop.close()
    

    输出:

    1 done
    2 done
    3 done
    

    【讨论】:

      【解决方案2】:

      规范的方式是将结果推送到asyncio.Queue,就像crawler example 一样。 此外,明智的做法是为从输入队列获取新作业的下载任务运行有限数量,而不是产生一百万个新任务。

      【讨论】:

        【解决方案3】:

        据我了解,根据文档,requestsFutures(或者可以使用 asyncio.ensure_future 轻松转换为 Future)。

        Future 对象有一个方法.add_done_callback。 因此,您可以为每个请求添加回调,然后执行gather

        Docs for Future.add_done_callback

        【讨论】:

        • 在编写非常低级别的内容之前不要使用add_done_callback
        猜你喜欢
        • 2012-02-15
        • 1970-01-01
        • 2016-02-25
        • 1970-01-01
        • 2012-10-16
        • 2019-10-09
        • 2017-07-05
        • 1970-01-01
        • 2015-07-01
        相关资源
        最近更新 更多