Python 如何在异步函数中使用“产量”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37549846/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use 'yield' inside async function?
提问by Ильдар
I want to use generator yield and async functions. I read this topic, and wrote next code:
我想使用生成器 yield 和 async 函数。我阅读了这个主题,并编写了下一个代码:
import asyncio
async def createGenerator():
mylist = range(3)
for i in mylist:
await asyncio.sleep(1)
yield i*i
async def start():
mygenerator = await createGenerator()
for i in mygenerator:
print(i)
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(start())
except KeyboardInterrupt:
loop.stop()
pass
But i got the error:
但我得到了错误:
SyntaxError: 'yield' inside async function
SyntaxError:异步函数中的“yield”
How to use yield generator in async function?
如何在异步函数中使用产量生成器?
回答by Mikhail Gerasimov
Upd:
更新:
Starting with Python 3.6 we have asynchronous generatorsand able to use yield
directly inside coroutines.
从 Python 3.6 开始,我们有异步生成器,可以yield
直接在协程内部使用。
import asyncio
async def async_generator():
for i in range(3):
await asyncio.sleep(1)
yield i*i
async def main():
async for i in async_generator():
print(i)
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main())
finally:
loop.run_until_complete(loop.shutdown_asyncgens()) # see: https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.shutdown_asyncgens
loop.close()
Old answer for Python 3.5:
Python 3.5 的旧答案:
You can't yield
inside coroutines. Only way is to implement Asynchronous Iteratormanually using __aiter__
/__anext__
magic methods. In your case:
你不能yield
在协程里面。唯一的方法是使用/魔术方法手动实现异步迭代器。在你的情况下:__aiter__
__anext__
import asyncio
class async_generator:
def __init__(self, stop):
self.i = 0
self.stop = stop
async def __aiter__(self):
return self
async def __anext__(self):
i = self.i
self.i += 1
if self.i <= self.stop:
await asyncio.sleep(1)
return i * i
else:
raise StopAsyncIteration
async def main():
async for i in async_generator(3):
print(i)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Output:
输出:
0
1
4
回答by rominf
New Python 3.6 comes with support for asynchronous generators.
新的 Python 3.6 支持异步生成器。
PS: On the moment of writing Python 3.6 is still beta. If you are on GNU/Linux or OS X and you cannot wait you can try new Python with pyenv.
PS:在编写 Python 3.6 的那一刻仍然是测试版。如果您在 GNU/Linux 或 OS X 上并且迫不及待,您可以使用pyenv尝试新的 Python 。
回答by Matus
This should work with python 3.6 (tested with 3.6.0b1):
这应该适用于 python 3.6(用 3.6.0b1 测试):
import asyncio
async def createGenerator():
mylist = range(3)
for i in mylist:
await asyncio.sleep(1)
yield i*i
async def start():
async for i in createGenerator():
print(i)
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(start())
except KeyboardInterrupt:
loop.stop()
pass