2

I watched an asyncio Pycon video on youtube where the presenter in one of her examples said she was using asyncio.create_task to run the coroutine instead of await, as await would block the execution of the coroutine until whatever it is awaiting is complete. I thought asyncio.create_task returns a Task which needs to be await. Nevertheless, I ran test using the following code and I am somewhat surprised by its result.

async def say_hello():
    print("Hello")
    await asyncio.sleep(0.5)
    print("World")

async def run_coro(coro):
    asyncio.create_task(coro)

asyncio.run(run_coro(say_hello()))

The code above prints only Hello. I figured that asyncio.create_task in run_coro stops execution as soon as it reaches the await line in say_hello. If I rewrite say_hello as follows and the run it using run_coro I see all the lines before `await asyncio.sleep(0.5) printed on the terminal

async def say_hello():
    print("Hello")
    print("Hello")
    print("Hello")
    print("Hello")
    await asyncio.sleep(0.5)
    print("World")

If I rewrite run_coro as follows then all the lines get printed as expected:

async def run_coro(coro):
    asyncio.create_task(coro)
    await asyncio.sleep(1)

Can anyone tell why?

abdullahalali
  • 396
  • 2
  • 5
  • 18
user6037143
  • 516
  • 5
  • 20

2 Answers2

2

Because

  1. asyncio.run actually calls loop.run_until_complete, which means the main program will exit as soon as run_coro returns. So the scheduler does not have chance to run say_hello
  2. asyncio.create_task(coro) runs coro in the background

if you change your code to

async def run_coro(coro):
    asyncio.create_task(coro)
    await asyncio.sleep(0.49)

coro actually only runs for 0.49 seconds, so you still can not see print("World")

1

You need to suspend the current task by blocking coroutine or using await so that the next task can be done, which is why having await asyncio.sleep(1) work as expected. See more: here

abdullahalali
  • 396
  • 2
  • 5
  • 18