52

In Python 3.6, I am able to use yield inside a coroutine. However I am not able to use yield from.

Below is my code. On line 3 I await another coroutine. On line 4 I try to yield from a file. Why won't Python 3.6 allow me to do that?

async def read_file(self, filename): with tempfile.NamedTemporaryFile(mode='r', delete=True, dir='/tmp', prefix='sftp') as tmp_file: await self.copy_file(filename, tmp_file) yield from open(tmp_file) 

Here's the exception Python 3.6 raises for the above code:

 File "example.py", line 4 yield from open(tmp_file) ^ SyntaxError: 'yield from' inside async function 
2
  • Is it true that the @asyncio.coroutine decorator can be used to enable "yield from" in an async function? From the asyncio documentation: "@asyncio.coroutine¶ Decorator to mark generator-based coroutines. This enables the generator use yield from to call async def coroutines, and also enables the generator to be called by async def coroutines, for instance using an await expression." I'm not sure if this would work with the code you wrote above... Commented Jan 26, 2018 at 11:06
  • See also stackoverflow.com/questions/39637675/… Commented Jan 26, 2018 at 11:32

1 Answer 1

68

According to PEP 525, which introduces asyncronous generators in Python 3.6:

Asynchronous yield from

While it is theoretically possible to implement yield from support for asynchronous generators, it would require a serious redesign of the generators implementation.

yield from is also less critical for asynchronous generators, since there is no need provide a mechanism of implementing another coroutines protocol on top of coroutines. And to compose asynchronous generators a simple async for loop can be used:

async def g1(): yield 1 yield 2 async def g2(): async for v in g1(): yield v 

As you can see, the answer boils down to "it would be too hard to implement, and you don't need it anyway".

Sign up to request clarification or add additional context in comments.

3 Comments

You do need it though, to delegate transparently to sub-generators making full capability of yield expressions (i.e. receiving values as well as yielding them). Without yield from it's a mess of passing on yielded values to the caller, passing on received values to the sub-generators, and handling all of the special exceptions.
This only gives an argument as to why supporting 'yield from' an async generator is hard. Not why yielding from a normal generator can't be possible.
@Kroppeb the reason you can't yield from a normal generator is that normal generators are blocking and you shouldn't be blocking in an async method.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.