Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is the task at `create_task()` executed in asyncio?

In the following code:

import asyncio

async def task_func():
    print('in task_func')
    return 'the result'


async def main(loop):
    print('creating task')
    task = loop.create_task(task_func())
    print('waiting for {!r}'.format(task))
    await asyncio.sleep(2)
    return_value = await task
    print('task completed {!r}'.format(task))
    print('return value: {!r}'.format(return_value))


event_loop = asyncio.new_event_loop()
try:
    event_loop.run_until_complete(main(event_loop))
finally:
    event_loop.close()

When I execute the code, the result is the following:

creating task
waiting for `<Task pending coro=<task_func() running at <ipython-input-29-797f29858344>:1>>`
in task_func
task completed `<Task finished coro=<task_func() done, defined at <ipython-input-29-797f29858344>:1> result='the result'>`
return value: 'the result'

But I don't understand when the code you set at loop.create_task(task_func()) is executed. Specifically, I assumed when you add a task to the event loop, it is executed soon, so I thought in task_func is printed before waiting for <Task....

Then I found it is always executed after the waiting for <Task..., so I added await asyncio.sleep(2), but only found that the in task_func is printed before the finish of 2 seconds.

I also added task_func_2() which is practically the same as task_func() and create its task below task = loop.create_task(task_func()) but do NOT add return_value_2 = await task2, so the await does not execute the task (otherwise the task_func_2() is never executed).

So now I got confuesed. When is the task is executed after it is added to the event loop in loop.create_task()?

like image 585
Blaszard Avatar asked May 03 '18 13:05

Blaszard


People also ask

What is Create_task in Python?

create_task() function to create Tasks, or the low-level loop. create_task() or ensure_future() functions. Manual instantiation of Tasks is discouraged. To cancel a running Task use the cancel() method. Calling it will cause the Task to throw a CancelledError exception into the wrapped coroutine.

Which function is used to run Awaitables concurrently in Asyncio?

gather() method - It runs awaitable objects (objects which have await keyword) concurrently. Like in the above example, we used func1 and func2 within gather method. When all awaitables are completed successfully, the result is an aggregate list of returned values. asyncio.

What are tasks in Asyncio?

Tasks within Asyncio are responsible for the execution of coroutines within an event loop. These tasks can only run in one event loop at one time and in order to achieve parallel execution you would have to run multiple event loops over multiple threads.

How do I stop Asyncio tasks?

A Task is created and scheduled for its execution through the asyncio. create_task() function. Once scheduled, a Task can be requested for cancellation through task. cancel() method.


1 Answers

Specifically, I assumed when you add a task to the event loop, it is executed soon, so I thought in task_func is printed before waiting for <Task....

"Executed soon" doesn't mean executed right away. Instead, you can think of it as "executed the first chance we get," we being the event loop. Since print immediately follows the call to create_task, at that point the event loop hasn't yet had a chance to run at all. To give event loop a chance to run, you must return to the event loop, either by returning from the current coroutine, or by awaiting something that blocks.

When you await a blocking coroutine such as asyncio.sleep(), the coroutine will temporarily suspend itself and relinquish control to the event loop. The event loop will look at what else there is to do before the sleep elapses and will find the tasks scheduled using create_task in its run queue. This is why task_func and task_func_2 are executed when the main coroutine awaits the sleep - but not before that, and regardless of whether you await them in particular or something else that blocks.

awaiting a coroutine such as task_func means requesting its result then and there, and being prepared to wait for it if the coroutine suspends. (Waiting on something that suspended automatically defers execution to the event loop, allowing other coroutines to make progress.) Although the implementation differs, an await is conceptually similar to joining a thread.

like image 130
user4815162342 Avatar answered Sep 30 '22 11:09

user4815162342