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()
?
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.
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.
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.
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.
Specifically, I assumed when you add a task to the event loop, it is executed soon, so I thought
in task_func
is printed beforewaiting 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.
await
ing 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 join
ing a thread.
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