【问题标题】:Converting from generator-based to native coroutines从基于生成器的协程转换为原生协程
【发布时间】:2020-02-27 16:42:43
【问题描述】:

我已经使用 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 中阅读以下通知:

对基于生成器的协程的支持已被弃用,并计划在 Python 3.10 中移除。

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

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

【问题讨论】:

  • @RomanPerekhrest:嗯,这是我的问题,不是吗?我会用“你做不到”作为答案,但这意味着用协程做这样的事情的能力将在没有任何替代的情况下离开 Python,这将是不方便的。当然,还有其他方法可以实现相同的目标,所以这不是什么大不了的事,但不幸的是。

标签: python coroutine python-asyncio


【解决方案1】:

还有Asynchronous Generators ...

所以我们在异步上下文中仍然具有 这种能力
至于理论 - 提到的 PEP 525 提供了很好的描述,绝对值得一读。
我将发布一个准备好的说明性示例(用于异步 averager),其中包含 initializationsafe finalization

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

【讨论】:

    猜你喜欢
    • 2015-12-11
    • 2017-02-06
    • 2017-06-04
    • 2017-09-02
    • 2018-03-13
    • 2023-03-05
    • 2018-10-14
    • 2018-03-31
    • 2011-08-22
    相关资源
    最近更新 更多