【问题标题】:Why do we need the asyncio.coroutine decorator?为什么我们需要 asyncio.coroutine 装饰器?
【发布时间】:2018-04-17 15:50:43
【问题描述】:

为什么我们需要asyncio.coroutine 装饰器?它提供什么功能?

例如:

# import asyncio
# @asyncio.coroutine
def gen():
    value = yield("Started")
    print(value)

a = gen()
a.send(None)
a.send("Done")

现在,如果我取消前两行的注释并使用 asyncio.coroutine 装饰器,我仍然会得到相同的输出。

我的意思是这已经是一个coroutine - 一个可以暂停并通过参数传入的函数。为什么我需要用另一个coroutineasyncio.coroutine 来装饰它?

【问题讨论】:

  • async defawait 语法直到 3.5 才可用,而 asyncio 在 3.4 中正式引入...
  • 现在我不确定你在问什么......你有一个正常的生成器函数,你可以将数据发送回 - 你已经能够在任何 asyncio 之前做到这一点完全...
  • 您可以将它们用作异步事件循环的一部分并让它们相互等待/睡眠/取消等...如果您熟悉扭曲,那么将asyncio IO 视为做同样事情的基础(没有所有现成的反应器和协议)...可能值得阅读教程或基本示例并从那里获取...
  • 在您的示例中,您不需要装饰器。它一无所获。只有在定义将传递给事件循环的协程时才使用它。即使这样,如果您的代码要在 3.4 上运行,您也只想使用装饰器;从 3.5 开始,您可以使用 async def
  • 我强烈建议您查看 asyncio 源代码以尝试理解这些内容(尤其是 asyncio/coroutines.py)。看起来文档和解释在查看代码后更加清晰(就像代码是解释的文档......)。

标签: python python-asyncio coroutine


【解决方案1】:

重要的是要了解generatorsasyncio coroutines - 是不同的东西。协程是使用生成器实现的,但(理论上)可以在没有它们的情况下实现。生成器 - 是协程实现的一部分。

由于asyncio 协程是使用生成器实现的,所以有时您可以将生成器用作协程而不会出错:

import asyncio


def main():
    yield from asyncio.sleep(1)
    print('done')


loop = asyncio.get_event_loop()
loop.run_until_complete(main())

结果:

done

但它不适用于所有类型的协程:

import asyncio


def main():
    # yield from asyncio.sleep(1)
    print('done')


loop = asyncio.get_event_loop()
loop.run_until_complete(main())

结果:

TypeError: An asyncio.Future, a coroutine or an awaitable is required

这就是为什么(除了few other 的东西)asyncio.coroutine 装饰器使用:

import asyncio


@asyncio.coroutine
def main():
    # yield from asyncio.sleep(1)
    print('done')


loop = asyncio.get_event_loop()
loop.run_until_complete(main())

结果:

done

但正如所有人已经指出的那样,今天它实际上并不重要:因为 Python 3.5 装饰器和 yield from 已被关键字 async defawait 替换,这不仅更好,而且有助于将协程从它们的实现中分离出来以更好的方式详细说明。

import asyncio


async def main():
    # await asyncio.sleep(1)
    print('done')


loop = asyncio.get_event_loop()
loop.run_until_complete(main())

【讨论】:

  • 抱歉,我对“但它不适用于所有协程”这句话有点困扰。在下面的代码中,您似乎在暗示 main 是一个协程......如何?这只是一个常规功能。此外,就“有时将生成器用作协程”而言,我正在查看的实现将接受任何生成器,只要它产生Noneyields from 被接受为协程的东西。这可能是一个实现细节,但仍然比“有时”更具启发性。
猜你喜欢
  • 2010-09-21
  • 2011-01-02
  • 2018-01-02
  • 2019-01-18
  • 2012-03-22
  • 2018-02-23
  • 2011-03-29
  • 2023-03-21
相关资源
最近更新 更多