Search code examples
pythonpython-3.xasync-awaitpython-asyncio

Python asyncio double await


For some reason I need to write a double await, but I don't exactly know why. Can someone explain this to me?

I've created a small example of the issue I ran into.

import asyncio
from random import randint

async def work():
    return randint(1, 100)

async def page():
    return asyncio.gather(*[
        work()
        for _ in range(10)
    ])

async def run():
    results = await (await page())
    return max(list(results))

result = asyncio.run(run())

It is the line results = await (await page()).


Solution

  • To actually execute awaitable objects you need to await on them.

    Your page here is coroutine function, when called, it returns a coroutine which is an awaitable object!

    When you say await page(), you're running the body of it. after execution it gives you(return) another awaitable object which is the result of calling asyncio.gather(). So you need to await on that too. That's why you need two await.

    If you don't you'd see:

    RuntimeError: await wasn't used with future
    

    You could do this nested await expression inside the calling coroutine:

    import asyncio
    from random import randint
    
    
    async def work():
        return randint(1, 100)
    
    
    async def page():
        return await asyncio.gather(*[work() for _ in range(10)])
    
    
    async def run():
        results = await page()
        return max(list(results))
    
    
    result = asyncio.run(run())
    print(result)