1
votes

There seem to be two kinds of generator-based coroutine:

  1. From a reply by Jim Fasarakis Hilliard:

    Generator-based coroutine: A generator (def + yield) that is wrapped by types.coroutine . You need to wrap it in types.coroutine if you need it to be considered a coroutine object.

  2. From Python in a Nutshell, which doesn't explicitly call it "generator-based coroutine":

    When you write Python code based on asyncio (ideally also using add-on modules from asyncio.org), you’ll usually be writing coroutine functions. Up to Python 3.4 included, such functions are generators using the yield from statement covered in “yield from (v3-only)” on page 95, decorated with @asyncio.coroutine , covered in “asyncio coroutines” on page 518;

    From https://www.python.org/dev/peps/pep-0492/#differences-from-generators

    generator-based coroutines (for asyncio code must be decorated with @asyncio.coroutine)

    http://masnun.com/2015/11/13/python-generators-coroutines-native-coroutines-and-async-await.html also calls it "generator-based coroutine".

Are the two kinds of generator-based coroutines the same concept?

If not, what are their differences in purposes and usages?

Thanks.

2

2 Answers

3
votes

As far as I’m concerned, async def is the proper way to define a coroutine. yield and yield from have their purpose in generators, and they are also used to implement “futures”, which are the low-level mechanism that handles switching between different coroutine contexts.

I did this diagram a few months ago to summarize the relationships between them. But frankly, you can safely ignore the whole business. Event loops have the job of handling all the low-level details of managing the execution of coroutines, so use one of those, like asyncio. There are also asyncio-compatible wrappers for other event loops, like my own glibcoro for GLib/GTK.

In other words, stick to the asyncio API, and you can write “event-loop-agnostic” coroutines!

2
votes

They're the same kind of coroutine. types.coroutine and asyncio.coroutine are just two separate ways to create them.

asyncio.coroutine is older, predating the introduction of async coroutines, and its functionality has shifted somewhat from its original behavior now that async coroutines exist.

asyncio.coroutine and types.coroutine have subtly different behavior, especially if applied to anything other than a generator function, or if asyncio is in debug mode.