2
votes

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?

1
Is there a reason why you want to implement your own switch coroutine? Practically all events loops consider their respective sleep(0) to do this. On top, not every event loop will respond properly to an empty yield.MisterMiyagi
@asyncio.coroutine is deprecated, but @types.coroutine isn't (and won't be), so you should use that. If you look carefully, asyncio.sleep uses that one internally as well.user4815162342

1 Answers

3
votes

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.