Issue
I'm trying to do this:
"An event loop runs in a thread (typically the main thread) and executes all callbacks and Tasks in its thread. While a Task is running in the event loop, no other Tasks can run in the same thread. When a Task executes an await expression, the running Task gets suspended, and the event loop executes the next Task."
https://docs.python.org/3/library/asyncio-dev.html#concurrency-and-multithreading
And I did this ugly example:
import asyncio
async def print_message(message):
print(message)
async def int_sum(a, b):
await print_message('start_sum')
result = a + b
await print_message('end_sum')
return result
async def int_mul(a, b):
await print_message('start_mul')
result = a * b
await print_message('end_mul')
return result
async def main():
result = await asyncio.gather(int_sum(4, 3), int_mul(4, 3))
print(result)
asyncio.run(main())
With "secuential-like" results:
$ python async_test.py
start_sum
end_sum
start_mul
end_mul
[7, 12]
But I want a "corroutine-like" output:
$ python async_test.py
start_sum
start_mul
end_sum
end_mul
[7, 12]
How can I do that?
Note: I'm not looking for a asyncio.sleep(n)
example, I'm looking for
"When a Task executes an await expression, the running Task gets suspended, and the event loop executes the next Task".
Solution
The point is, Tasks only give the control back to the event loop with yield
statement. In your example you already have three active tasks(add asyncio.all_tasks()
in the first line of int_sum
coroutine to confirm1) but for example int_sum
is not cooperating. it doesn't give the control back to the event loop. why ? Because you don't have any yield
.
A simple fix to this is to change your print_message
to:
async def print_message(message):
print(message)
await asyncio.sleep(0)
if you see the source code of asyncio.sleep
:
async def sleep(delay, result=None):
"""Coroutine that completes after a given time (in seconds)."""
if delay <= 0:
await __sleep0()
return result
...
And this is the body of the __sleep0()
(right above the sleep
):
@types.coroutine
def __sleep0():
"""Skip one event loop run cycle.
This is a private helper for 'asyncio.sleep()', used
when the 'delay' is set to 0. It uses a bare 'yield'
expression (which Task.__step knows how to handle)
instead of creating a Future object.
"""
yield
Now your output should be:
start_sum
start_mul
end_sum
end_mul
[7, 12]
1 Note: you do have three tasks, asyncio.gather
does that for you:
If any awaitable in aws is a coroutine, it is automatically scheduled as a Task.
Answered By - S.B
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.