There is something I can't understand in this code
import asyncio
async def fetch_data(param):
print(f"Do something with {param}...")
await asyncio.sleep(param)
print(f"Done with {param}")
return f"Result of {param}"
async def main():
task1 = asyncio.create_task(fetch_data(1))
task2 = asyncio.create_task(fetch_data(2))
result2 = await task2
print("Task 2 fully completed")
result1 = await task1
print("Task 1 fully completed")
return [result1, result2]
results = asyncio.run(main())
print(results)
The output is
Do something with 1...
Do something with 2...
Done with 1
Done with 2
Task 2 fully completed
Task 1 fully completed
['Result of 1', 'Result of 2']
I expected to see
Do something with 2...
In the first line, but it outputs Do something with 1... first. It seems just creating tasks will run the coroutine, while from what I read and saw, it only registers it in the event loop. The flow should be
- From
results = asyncio.run(main())the main is registered into event loop - Event loop runs the
main - Two tasks 1,2 are created and registered into the event loop, with status
ready - By
result2 = await task2, themainis suspendedfetch_data(2)is run
From this flow, I expect to see Do something with 2... in the first line. Why does this output the Do something with 1...? first?
To verify, I run this
import asyncio
async def fetch_data(param):
print(f"Do something with {param}...")
await asyncio.sleep(param)
print(f"Done with {param}")
return f"Result of {param}"
async def main():
task1 = asyncio.create_task(fetch_data(1))
task2 = asyncio.create_task(fetch_data(2))
results = asyncio.run(main())
print(results)
and the output is
Do something with 1...
Do something with 2...
None
Why are the couroutines running even without awaiting the tasks? Why does print(f"Done with {param}") not run in this version?
create_task()starts running task. If you don't want start it then use onlyawait fetch_data(2).awaitis NOT starting if you usedcreate_task()- it only waits for finishing it.coroutineandtask.fetch_datais a coroutine,task1is a task. When you runsawait coroutinethen it converts coroutine to task, starts it and wait for results. When you runsawait taskthen it is already running and it has to only wait for resultawaitis blocking code.create_task(coroutine1)orgather([coroutine1, coroutine2])