Fernando César
Fernando César

Reputation: 861

`asyncio.run()` does not wait for coroutine to finish

I'm running this code in Python 3.7.3

import asyncio

async def fun(time):
    print(f"will wait for {time}")
    await asyncio.sleep(time)
    print(f"done waiting for {time}")

async def async_cenas():
    t1 = asyncio.create_task(fun(1))
    print("after 1")
    t2 = asyncio.create_task(fun(2))
    print("after 2")

def main():
    t1 = asyncio.run(async_cenas())
    print("ok main")
    print(t1)

if __name__ == '__main__':
    main()
    print("finished __name__")

And getting this output:

after 1
after 2
will wait for 1
will wait for 2
ok main
None
finished __name__

I was expecting to see also:

done waiting for 1
done waiting for 2

I.e., why was expecting asyncio.run(X) would wait for the coroutines to complete before proceeding.

Upvotes: 2

Views: 4196

Answers (1)

alex_noname
alex_noname

Reputation: 32253

If you want to wait for the completion of all tasks spawned by the create_task, then you need to do it explicitly by, for example, just await for them in turn or asyncio facilities like gather or wait (the difference is described here). Otherwise, they will be canceled by the asyncio.run when exiting the main coroutine, which is passed to asyncio.run.

Example:

import asyncio

async def fun(time):
    print(f"will wait for {time}")
    await asyncio.sleep(time)
    print(f"done waiting for {time}")

async def async_cenas():
    t1 = asyncio.create_task(fun(1))
    print("after 1")
    t2 = asyncio.create_task(fun(2))
    print("after 2")
    await asyncio.wait({t1, t2}, return_when=asyncio.ALL_COMPLETED)
    # or just
    # await t1
    # await t2

def main():
    t1 = asyncio.run(async_cenas())
    print("ok main")
    print(t1)

if __name__ == '__main__':
    main()
    print("finished __name__")
after 1
after 2
will wait for 1
will wait for 2
done waiting for 1
done waiting for 2
ok main
None
finished __name__

Upvotes: 6

Related Questions