Let's say I have two functions which return similar results. I want to call both and take the results of whichever returns first. So lets say I have two async functions which wait 5 and 2 seconds like so:
import asyncio
from time import sleep
async def func_1():
for i in range(5):
print("func 1")
sleep(1)
return "slept for 5"
async def func_2():
for i in range(2):
print("func 2")
sleep(1)
return "slept for 2"
And I have a function which calls them like so:
async def competition():
task2 = asyncio.create_task(func_1())
task1 = asyncio.create_task(func_2())
done, pending = await asyncio.wait([task1, task2], return_when=asyncio.FIRST_COMPLETED)
print(len(pending))
print(len(done))
As you see the competition function uses asyncio.wait
to run the two tasks and returns the results based on the FIRST_COMPLETED
function. The documentation defines FIRST_COMPLETED
as:
The function will return when any future finishes or is cancelled.
Also, I run the competition
function as shown bellow.
asyncio.run(competition())
However, it does not return when one task is done. It returns when both are done. Furthermore, the asyncio.wait() method is defined as a concurrent executer.
Run awaitable objects in the aws iterable concurrently and block until the condition specified by return_when.
However, that is not what happens. The tasks run in a single thread and one runs after the other. So the result that I get if I run the code is this:
func 1
func 1
func 1
func 1
func 1
func 2
func 2
0
2
Am I missing anything? Or have I misunderstood how it works?
FYI: I am using python 3.10.
time.sleep
is a blocking call, you wantasyncio.sleep()
if you just want to sleep the coro, and not the entire program, otherwise you serialize your execution. - wkl