python - 从基于生成器的协程转换为 native 协程

标签 python coroutine python-asyncio

我已经使用 Python 多年,但只是逐渐研究了这门语言的一些比较晦涩的特性,因为我的大部分代码都是用于数据处理的。基于 yield 的生成器是我日常工具包的一部分,最近我阅读了有关协程的内容。我找到了一个类似的例子:

def averager():
    sum = 0.0
    n = 0
    while True:
        value = yield
        sum += value
        n += 1
        print(sum/n)

avg = averager()
next(avg) # prime the coroutine
avg.send(3)
avg.send(4)
avg.send(5)

它打印发送给它的值的平均值。我认为这样的东西可能对数据处理管道有用,所以我决定把它放在脑后。也就是说,直到我在 Python documentation 中阅读以下通知:

Support for generator-based coroutines is deprecated and is scheduled for removal in Python 3.10.

显然我想编写面向 future 的代码,所以在这一点上开始学习基于生成器的协程可能没有用。那么,我的问题是:如何使用原生 (asyncio) 协程来实现这个示例?我很难理解原生协程语法。

在尝试搜索答案时,我找到了一个 related question它有一个 comment和一个 answer这基本上是在说“你不能用 async 来做,而是用 yield 为基础的协程来做”。但是,如果这些都消失了,在 3.10+ 中是否有任何方法可以使用协程来做到这一点?

最佳答案

来了Asynchronous Generators ...

所以我们在异步上下文中仍然拥有那种力量
至于理论 - 提到的 PEP 525 提供了很好的描述,绝对值得一读。
我将发布一个准备好的说明性示例(用于异步 averager),包括初始化安全终结:

import asyncio

async def coro():
    print('running other coroutine in 3 sec ...')
    await asyncio.sleep(3)  # emulate working


async def averager():
    sum_ = n = 0
    while True:
        v = yield
        sum_ += v
        n += 1
        print(sum_ / n)
        await asyncio.sleep(0.1)


async def main():
    agen = averager()
    await agen.asend(None)
    print(agen.__name__, 'initialized ...')

    await agen.asend(3)
    print('another separate processing here ...')

    await coro()

    await agen.asend(4)
    await agen.asend(14)


loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(main())
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

程序输出:

averager initialized ...
3.0
another separate processing here ...
running other coroutine in 3 sec ...
3.5
7.0

关于python - 从基于生成器的协程转换为 native 协程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58658305/

相关文章:

python-3.x - 监控异步事件循环

python - Discord.py:事件循环关闭后重启机器人

python - 使用tensorflow求解代数时,训练后所有变量都变成了nan

python - gae-init 电话簿示例 : css not load correct?/

multithreading - 是否有任何领域应该优先考虑线程而不是协程?

android - 为什么在生命周期范围内 fragment 的上下文为空

python - Scrapy CrawlerRunner : Output missing

python - 如何从 aspx 页面抓取图像?

multithreading - Crystal 将线程池背后的想法转换为 Fibers/spawn

python - 在 Python3.6.1 中调用 loop.close asyncio.get_event_loop 后无法创建新的事件循环