为什么我们需要 asyncio.coroutine 装饰器?

Why do we need the asyncio.coroutine decorator?

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

例如:

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

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

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

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

重要的是要了解 generators and asyncio 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

这就是为什么(除了 东西)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())