The following code illustrates how to use coroutines with asyncio
.
The output of consecutive
and parallel_fail
is:
SLEEP for 2.5 seconds # 0
back after 2.5 seconds # 2.5
SLEEP for 2 seconds # 2.5
back after 2 seconds # 4.5
(printed after 0, 2.5, 2.5 and 4.5 seconds)
And the output of parallel
is:
SLEEP for 2.5 seconds # 0
SLEEP for 2 seconds # 0
back after 2 seconds # 2
back after 2.5 seconds # 2.5
The outputs of consecutive
and parallel
are expected.
But why is parallel_fail
like consecutive
, and not like parallel
?
One would expect that await something
is equivalent to a = something
followed by await a
, right?
import asyncio
async def f(n):
print(f'SLEEP for {n} seconds')
await asyncio.sleep(n)
print(f'back after {n} seconds')
async def consecutive():
print('consecutive:')
await f(2.5)
await f(2)
async def parallel():
print('parallel:')
a = asyncio.create_task(f(2.5))
b = asyncio.create_task(f(2))
await a
await b
async def parallel_fail():
print('parallel fail:')
await asyncio.create_task(f(2.5))
await asyncio.create_task(f(2))
asyncio.run(consecutive())
print('----------------------')
asyncio.run(parallel())
print('----------------------')
asyncio.run(parallel_fail())
The behaviour you observe in parallel()
is as follows:
f(2.5)
and assign the task to variable a
f(2)
and assign the task to variable b
a
to finish (this will take 2.5 seconds)b
(that is scheduled) finished after 2 secondsawait b
doesn't await for anything - because task b
finishedSo here you see parallel running.
The behaviour you observe in parallel_fail()
is as follows:
f(2.5)
and immediately await it (this takes 2.5sec)f(2)
and immediately await it (this takes 2sec)Here you see normal sequential running.