Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the "yield from" syntax do in asyncio and how is it different from "await"

From the perspective of someone who has written asyncio code but is looking to better understand the inner workings, what is yield from, await and how are those useful for allowing asynchronous code?

There is one highly upvoted question asking about the uses of the yield from syntax and one explaining async and await, but both go in depth about different topics and are not really a concise explanation of the underlying code and how it fits in with asyncio.

like image 938
Azsgy Avatar asked May 29 '17 22:05

Azsgy


People also ask

What does await do in Asyncio?

The keyword await passes function control back to the event loop. (It suspends the execution of the surrounding coroutine.) If Python encounters an await f() expression in the scope of g() , this is how await tells the event loop, “Suspend execution of g() until whatever I'm waiting on—the result of f() —is returned.

Does await always yield?

If its target yield s, await "passes on" the suspension to its own caller. This allows to suspend an entire stack of coroutines that all await each other. If its target returns s, await catches the return value and provides it to its own coroutine.

How does async await work in Python?

An async function uses the await keyword to denote a coroutine. When using the await keyword, coroutines release the flow of control back to the event loop. To run a coroutine, we need to schedule it on the event loop. After scheduling, coroutines are wrapped in Tasks as a Future object.


1 Answers

Short answer:

yield from is an old way to wait for asyncio's coroutine.

await is a modern way to wait for asyncio's coroutine.

Detailed answer:

Python has generators - special kind of functions that produces a sequence of results instead of a single value. Starting with Python 3.3 yield from expression was added. It allows one generator to delegate part of its operations to another generator.

Starting with Python 3.4 asyncio module was added to standard library. It allow us to write clear and understandable asynchronous code. While technically asyncio's coroutines could be implemented different ways, in asyncio they were implemented using generators (you can watch for excellent video where shown how generators can be used to implement coroutines). @asyncio.coroutine was a way to make coroutine from generator and yield from was a way to await for coroutine - just details of implementation.

That's how happened that yield from started to be used for two "different things".

Starting with Python 3.5 (see PEP 492) coroutines got new syntax. Now you can define coroutine with async def and await for it using await expression. It's not only shorter to write, but also makes clearer to understand that we work with asyncio's coroutines.

If you're using Python 3.5+ you can forget about using yield from for asyncio's coroutines and use await for it.

like image 52
Mikhail Gerasimov Avatar answered Sep 21 '22 15:09

Mikhail Gerasimov