0

I'm trying to learn more about coroutines, and the event loop in asyncio.

To my knowledge, a coroutine is a generator function. You can define a coroutine with async def. All the things that you can do to a generator functon, you can do to a coroutine. You can do coroutine.send(None), coroutine.throw(Exception), coroutine.close(). Now I have 2 questions about coroutines :

  1. When you add yield to a function it become a generator functon. This means that you have to include yield in every generator at least once. With most coroutines (like in discord.py) I do not see the yield key word in it at all! So how are they generators? Maybe the await keyword does yielding or something? Please explain.

  2. If generators and coroutines are the same, why do they have different names?

Now I think I know a little bit about generator functions, they yield, you can send them stuff and even exceptions. And coroutines are the same I think.

So, I know this: the event loop stops a coroutine when it sees the await keyword (this keyword just calls .__await__() method). And then it just executes the function after that keyword then moves on to a different task. Simple enough.

But i do not understand how this gives back control to the event loop.

Perhaps the event loop does this when running a task : coroutine.send(None) so it waits till a yield to context switch? So maybe the await is a yield? But if it does yield, that would make it a generator method and the actual coroutine is not yielding but the __await__() is?

Very confusing stuff. Could someone explain what await does and what the method .__await__() does?

So to wrap my questions up:

  1. What is the difference between a Generator functon and a Co-routine?
  2. What are the different use cases between those two?
  3. How do they work differently?
  4. How does asyncio run co-routines until the await?
  5. What does __await__() method do?
  6. Why don't I see any yields in co-routines?
  • 1
    Generator != Coroutine. A generator lazily evaluates an expression which can be iterated over. A Coroutine starts work on something but Python can go do other things while the result of the coroutine is being "awaited". Generators are not running on the side, they are running in the foreground and you don't do other things while it generates. You can create a Coroutine that is a Generator, where you are iterating over some result set asynchronously awaiting each result, but they are entirely separate entities in python for separate use cases. – Roman Czerwinski Apr 24 '21 at 15:49
  • @RomanCzerwinski Are you telling be that i can run a co-routine and do something else? To my knowledge, that is not possible, only context switching between many thing to make it apear concurent is possible. (Which is what asyncio does) Could you give me an example or something? And i dont understand how they are different. And what does await actually do? Appreciate the response. – user15755358 Apr 24 '21 at 16:22
  • Maybe read this article https://medium.com/analytics-vidhya/python-generators-coroutines-async-io-with-examples-28771b586578#:~:text=async%2Fawait%20keywords%20are%20introduced,always%20coroutines%2C%20even%20without%20await. – Roman Czerwinski Apr 25 '21 at 00:43
  • I read a little bit of the article and saw this: "Coroutine vs Generator: Coroutine is a generator that follows certain conventions. 1.coroutine yields control to another coroutine and can resume execution from the point it gives up control. 2.coroutines are data consumers while generators are data producers 3.can send values to generator based coroutines (using send() & (yield) statement) after it is initiated while regular generators can’t." Now cant generators do literally ALL these things? Gens can recieve data with `.send()` and `.throw()` – user15755358 Apr 25 '21 at 10:30
  • See the linked question. For specific discussion of how `await` works, also see [this lecture](https://youtu.be/7JtNiwCH_OA). – user4815162342 Apr 26 '21 at 07:49

0 Answers0