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 :
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 theawait
keyword does yielding or something? Please explain.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:
- What is the difference between a Generator functon and a Co-routine?
- What are the different use cases between those two?
- How do they work differently?
- How does asyncio run co-routines until the await?
- What does
__await__()
method do? - Why don't I see any yields in co-routines?