Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

asyncio create_task to run forever

Tags:

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.

like image 862
slaw Avatar asked May 29 '18 20:05

slaw


People also ask

How do you start a coroutine forever?

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?

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.

What is Asyncio Create_task?

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.

Which function is used to run Awaitables concurrently in Asyncio?

gather() method - It runs awaitable objects (objects which have await keyword) concurrently.


1 Answers

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.

like image 106
user4815162342 Avatar answered Oct 22 '22 08:10

user4815162342