What is the differnce between asyncio.coroutime and types.coroutine decorators?

Viewed 180

Practicing writing coroutines in python 3.6, Noticed that both in:

from asyncio import coroutine

And in:

from types import coroutine

There are 2 decorators which on first glance do the same..

Reading the documentation of first(from asyncio)

Decorator to mark coroutine

And the second one (from types):

Convert regular generator function to coroutine.

Confused me even more.. I know i can use async yield from in python3.6, so i get lost to really understand the difference between the two.

Please assist

2 Answers

With the advent of async def syntax, both decorators are rarely used, and asyncio.coroutine is officially deprecated.

The types.coroutine decorator is still useful as a low-level tool for creating a coroutine out of a generator. That kind of thing is useful when crafting primitives for a custom event loop implementation. With @types.coroutine you can create a coroutine out of a barebones generator, whose yield yields a value of your choice directly to the event loop.

For example, a sleep coroutine implementation could look like this:

@types.coroutine
def sleep(delay):
    deadline = time.time() + delay
    yield 'sleep_until', deadline

This creates a coroutine similar to the one created with async def, but with the magic ability to communicate with a compatible event loop, which might contain code like this:

def run(self):
    while self._to_run:
        coro = self._to_run.popleft()
        try:
            cmd, arg = coro.send(None)
        except StopIteration:
            continue
        if cmd == 'sleep_until':
            self._to_wake[arg] = coro
    time.sleep(min(self._to_wake) - time.time())
    self._to_run.extend(coro for t, coro in self._to_wake.items()
                        if t <= time.time())

For more details see this lecture by David Beazley where a full-featured event loop is built in front of a live audience. (Don't be put off by the use of yield from - the newer async def works exactly the same way.)

If you use Python 3.5+ you don't need to think about it.

Modern way to create coroutine is to define it with async def. If you're using recent Python version just follow relevant documentation.


If you interested in retrospective:

asyncio.coroutine decorator is an old way to create coroutine people used before Python 3.5.

types.coroutine is just an utility function mostly used internally in Python. As jonrsharpe noted asyncio.coroutine uses types.coroutine in its implementation. It's a strange thing it happened to be public, I've never seen anybody used it. You probably shouldn't also :)

Related