首页 > 解决方案 > 确保 aiohttp/asyncio 中递归函数的未来

问题描述

我遇到了在事件循环中未正确调用递归函数的问题。我有以下内容:

async def get_response(session, url, attempt=0):
    async with session.get(url) as response:
        if response.status == 200:
            return await response.json()
        elif attempt < 3:
            # This never gets called, a coroutine is returned
            return get_response(session, url, attempt + 1)
        else:
            return None

async def main(loop):
    output = []
    urls = ["https://httpbin.org/json"]
    async with aiohttp.ClientSession(loop=loop) as session:
        tasks = []
        for url in urls:
            tasks.append(asyncio.ensure_future(get_response(session, url)))
        for future in await asyncio.gather(*tasks):
            output.append(future)
    return output

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    output = loop.run_until_complete(main(loop))

问题出现在get_responseattempt < 3实际上不会再次运行该功能的地方。上面的代码可以正常工作,因为https://httpbin.org/json将返回 200 代码。如果我错了,请纠正我(因为我可能是),但我在想,既然函数的迭代不在任务列表中,main那么它实际上不会运行?我调试时得到的回报是一个实际的协程对象,而不是None我想要的。

future确保在必要时再次调用a 中的递归函数的正确方法是什么?

标签: pythonpython-asyncio

解决方案


get_responseasync 一样,您需要在调用它时等待它,即使是从它本身这样做。所以,你需要改变:

            return get_response(session, url, attempt + 1)

到:

            return await get_response(session, url, attempt + 1)

推荐阅读