Reputation: 758
In python's asyncio asynchronous programming (version 3.7 or below), if I would like to manually let a coroutine gives back its control to the main event loop , I can use this code:
@asyncio.coroutine
def switch():
yield
return
async def task():
# ...do something
# ...
await switch() # then this coroutine will be suspended and other will be triggered
# ...
# ... do something else when it's triggered again.
However in python3.8 "@coroutine" decorator is deprecated . And besides I could not use yield in a 'async def' (since it will define a async generator but not coroutine) . So how could I achive the same function?
Upvotes: 5
Views: 2214
Reputation: 50096
TLDR: Do not use an explicit yield
to switch coroutines. For asyncio
, use asyncio.sleep(0)
instead.
Practically all event loops consider their respective sleep
with a duration of 0 to mean "let other coroutines run".
For asyncio
, use asyncio.sleep(0)
to let other coroutines run.
async def task():
# ...do something
# ...
await asyncio.sleep(0) # then this coroutine will be suspended and other will be triggered
# ...
# ... do something else when it's triggered again.
Sleeping (
asyncio
)
sleep()
always suspends the current task, allowing other tasks to run.
Checkpoints (
trio
)
… it’s useful to know that
await trio.sleep(0)
is an idiomatic way to execute a checkpoint without doing anything else …
Time (
curio
)
Sleep for a specified number of seconds. If the number of seconds is 0, execution switches to the next ready task (if any).
If for some reason an explicit yield
to the event loop is needed, create a custom class and yield
in its __await__
special method.
class Switch:
"""Switch coroutines by yielding to the event loop"""
def __await__(self):
yield
Note that this sends a bare None
to the event loop. Whether and how an event loop handles this signal depends on the async library used.
Upvotes: 8