I have the following code
import asyncio loop = asyncio.get_event_loop() async def while_loop(): n = 0 while True: print(f"{n}") await asyncio.sleep(2) n = n+1 async def some_func(): await asyncio.sleep(5) print("Some Func") future = loop.create_task(while_loop()) loop.run_until_complete(some_func())
I expected the while_loop
function to run forever but it seems to only executes as a result of calling run_until_complete
and it stops printing the while loop once some_func
is finished executing. The output I see is:
0 1 2 Some Func
I expected the numbers to keep printing even after some_func
is completed.
0 1 2 Some Func 3 4 5 6 . . .
The only way to get more numbers printed is to call some_func
again.
Start the coroutine using loop. create_task() , run loop. run_forever() , and let it do the rest. Finally a clear explanation of how to go about adding tasks to the loop after run_until_complete() blocks the main thread.
How many times should Asyncio run () be called? It should be used as a main entry point for asyncio programs, and should ideally only be called once. New in version 3.7.
The method create_task takes a coroutine object as a parameter and returns a Task object, which inherits from asyncio. Future . The call creates the task inside the event loop for the current thread, and starts the task executing at the beginning of the coroutine's code-block.
gather() method - It runs awaitable objects (objects which have await keyword) concurrently.
I expected the numbers to keep printing even after
some_func
is completed.
The argument to run_until_complete
controls how long the event loop is run. And once the event loop stops running, all coroutines are effectively suspended, not just the one that you've been waiting for. But you do have different options:
loop.run_until_complete(some_func())
- what you already used; run the event loop until the some_func
coroutine finishes. Executes other coroutines in parallel during that time as well, but also stops executing them as soon as the event loop finishes.
loop.run_forever()
- run the event loop until some coroutine or callback invokes loop.stop()
. If none of them do that, then the event loop will not halt, even if all the coroutines come to an end. In your case you'd call loop.create_task(while_loop())
followed by loop.create_task(some_func())
and then loop.run_forever()
.
loop.run_until_complete(asyncio.gather(while_loop(), some_func()))
run the event loop until both the specified coroutines finish. This (wait for all the tasks) is apparently what you expected loop.run_until_complete()
to do automatically even if you name only one, except it doesn't work like that, it stops as soon as the specified coroutine finishes. asyncio.gather
can be used to wait for multiple coroutines at once. For a more fine-tuned control of waiting, also see asyncio.wait
.
Since one of your coroutines runs forever, the last two options will be equivalent and will result in the expected output.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With