Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple async calls blocking

My code:

import asyncio

async def test(i):
    await asyncio.sleep(i)
    print('test')

async def main():
    await test(2)
    await test(2)
    await test(2)

asyncio.get_event_loop().run_forever(main())

I was expecting for it to sleep for three seconds, then print out 'test' three times, but instead it waits 2 seconds before every 'test' separately (so last 'test' gets printed at 6 seconds).

What have I understood wrong, and how do I fix this to work as I expected?

like image 213
Markus Meskanen Avatar asked Apr 20 '17 11:04

Markus Meskanen


People also ask

Can you have multiple async functions?

You can call multiple asynchronous functions without awaiting them. This will execute them in parallel. While doing so, save the returned promises in variables, and await them at some point either individually or using Promise.

How do I stop async calls?

You can cancel an asynchronous operation after a period of time by using the CancellationTokenSource. CancelAfter method if you don't want to wait for the operation to finish.

Can async be blocking?

Async is widely considered to be non-blocking.

Can one async have multiple awaits?

In order to run multiple async/await calls in parallel, all we need to do is add the calls to an array, and then pass that array as an argument to Promise. all() . Promise. all() will wait for all the provided async calls to be resolved before it carries on(see Conclusion for caveat).


1 Answers

await suspends the execution of the current function until the future has returned. In test, that makes the function wait for 2 seconds until asyncio.sleep has returned, before printing. In main, it makes the function wait until test has returned (which it does after print which it does after sleep has returned), before continuing on the next line with the next await test.

If you want to execute all test at the same time and have them each print at once after two seconds, you can use asyncio.gather:

async def main():
    await asyncio.gather(test(2), test(2), test(2))

This schedules three test coroutines on the event loop at the same time and awaits all their combined results, which will arrive in ~2 seconds.

You could also fire and forget the coroutines without awaiting their completion:

def main():
    asyncio.ensure_future(test(2))
    asyncio.ensure_future(test(2))
    asyncio.ensure_future(test(2))
like image 134
deceze Avatar answered Sep 29 '22 12:09

deceze