Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I 'yield from' inside an async function?

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
like image 341
Akilesh Avatar asked Nov 19 '17 11:11

Akilesh


People also ask

Can you return from an async function?

Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise. Note: Even though the return value of an async function behaves as if it's wrapped in a Promise.resolve , they are not equivalent.

Why await only works inside an async function?

async and await are both meta keywords that allow asynchronous code to be written in a way that looks synchronous. An async function tells the compiler ahead of time that the function will be returning a Promise and will not have a value resolved right away. To use await and not block the thread async must be used.

Do async functions return immediately?

With that design, you call the asynchronous function, passing in your callback function. The function returns immediately and calls your callback when the operation is finished. With a promise-based API, the asynchronous function starts the operation and returns a Promise object.

Is only allowed within async functions?

The error "await expression is only allowed within an async function" occurs when the await keyword is used inside of a function that was not marked as async . To solve the error and use the await keyword, mark the directly enclosing function as async .


1 Answers

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".

like image 151
Zero Piraeus Avatar answered Oct 09 '22 11:10

Zero Piraeus