@ types.coroutine和@asyncio.coroutine装饰器之间有什么区别?

时间:2016-09-22 11:23:14

标签: python asynchronous python-3.5

文件说:

  

@ asyncio.coroutine

     

装饰器用于标记基于生成器的协同程序。这使得生成器使用yield可以调用异步def协同程序,也可以   使异步def协同程序能够调用生成器   使用await表达式的实例。

_

  

@ types.coroutine(gen_func)

     

此功能可转换发生器   函数到一个coroutine函数,返回一个基于生成器的函数   协程。基于发电机的协程仍然是发电机   迭代器,但也被认为是一个协程对象   awaitable。但是,它可能不一定实现__await__()   方法

似乎目的是相同的 - 将生成器标记为协程(Python3.5中的async def以及某些功能的更高版本。)

当需要使用asyncio.coroutine时需要使用types.coroutine,差异是什么?

2 个答案:

答案 0 :(得分:3)

不同之处在于您是否有收益率声明。 这是代码:

from types import coroutine as t_coroutine
from asyncio import coroutine as a_coroutine, ensure_future, sleep, get_event_loop


@a_coroutine
def a_sleep():
    print("doing something in async")
    yield 1


@t_coroutine
def t_sleep():
    print("doing something in types")
    yield 1


async def start():
    sleep_a = a_sleep()
    sleep_t = t_sleep()
    print("Going down!")


loop = get_event_loop()
loop.run_until_complete(start())

在这个示例中,一切看起来都相同 - 这里是来自pycharm的调试信息(我们正站在"走下去!"行)。控制台上还没有打印任何内容,因此功能尚未开始。

PyCharm Debug

如果删除yield types版本会立即启动!

from types import coroutine as t_coroutine
from asyncio import coroutine as a_coroutine, ensure_future, sleep, get_event_loop


@a_coroutine
def a_sleep():
    print("doing something in async")


@t_coroutine
def t_sleep():
    print("doing something in types")


async def start():
    sleep_a = a_sleep()
    sleep_t = t_sleep()
    print("Going down!")


loop = get_event_loop()
loop.run_until_complete(start())

现在我们在控制台中打印了doing something in types。这是调试信息:

new debug info

如您所见,会在调用后立即启动,如果没有结果并返回无。

至于使用方法,您应始终使用asyncio版本。如果您需要像 fire一样运行它并忘记(立即运行并稍后获得结果) - 使用ensure_future函数。

答案 1 :(得分:0)

另一个细微的区别:用@asyncio.coroutine装饰的基于生成器的协程将测试True中的asyncio.iscoroutinefunction(),而用@types.coroutine装饰的那些协程将测试False

# testcoro.py
import asyncio
import inspect
import types

@asyncio.coroutine
def old_coro_with_asyncio():
    yield from asyncio.sleep(1)

@types.coroutine
def old_coro_with_types():
    yield from asyncio.sleep(1)

if __name__ == "__main__":
    for coro in (old_coro_with_asyncio, old_coro_with_types):
        print(coro.__name__, 'iscoroutine:', asyncio.iscoroutine(coro))
        print(coro.__name__, 'iscoroutinefunc:', asyncio.iscoroutinefunction(coro))

输出:

(py37) $ python3 testcoro.py 
old_coro_with_asyncio iscoroutine: False
old_coro_with_asyncio iscoroutinefunc: True
old_coro_with_types iscoroutine: False
old_coro_with_types iscoroutinefunc: False

尽管如此,这两个都是可以等待的。


*还请注意,此区别不适用于其_results:将iscoroutinefunction()替换为iscoroutine()(用于测试协程对象),并替换old_coro_with_asyncio() + {{1 }}的评估结果均为False。