【问题标题】:What is the differnce between asyncio.coroutime and types.coroutine decorators? [duplicate]asyncio.coroutine 和 types.coroutine 装饰器有什么区别? [复制]
【发布时间】:2019-06-03 10:11:00
【问题描述】:
在 python 3.6 中练习编写coroutines,
注意到两者都在:
from asyncio import coroutine
在:
from types import coroutine
乍一看,有两个装饰器是一样的。
阅读first(from asyncio)的文档
装饰器来标记协程
第二个(来自types):
将常规生成器函数转换为协程。
让我更加困惑..
我知道我可以在 python3.6 中使用async yield from,所以我迷失了真正理解两者之间的区别。
请帮忙
【问题讨论】:
标签:
python-3.x
python-asyncio
coroutine
【解决方案1】:
如果您使用 Python 3.5+,则无需考虑。
创建协程的现代方式是用async def 定义它。如果您使用的是最新的 Python 版本,请关注相关的documentation。
如果您对回顾感兴趣:
asyncio.coroutine 装饰器是在 Python 3.5 之前创建协程的老方法。
types.coroutine 只是an utility function,主要在 Python 内部使用。正如 jonrsharpe 所指出的,asyncio.coroutine 在其实现中使用了types.coroutine。奇怪的是它碰巧是公开的,我从未见过有人使用它。你可能也不应该:)
【解决方案2】:
随着async def 语法的出现,这两个装饰器都很少使用了,asyncio.coroutine 正式成为deprecated。
types.coroutine 装饰器仍可用作从生成器创建协程的低级工具。在为自定义事件循环实现制作原语时,这种事情很有用。使用@types.coroutine,您可以从准系统生成器中创建协程,其yield 会直接向事件循环生成您选择的值。
例如,sleep 协程实现可能如下所示:
@types.coroutine
def sleep(delay):
deadline = time.time() + delay
yield 'sleep_until', deadline
这将创建一个类似于使用async def 创建的协程,但具有与兼容事件循环通信的神奇能力,其中可能包含如下代码:
def run(self):
while self._to_run:
coro = self._to_run.popleft()
try:
cmd, arg = coro.send(None)
except StopIteration:
continue
if cmd == 'sleep_until':
self._to_wake[arg] = coro
time.sleep(min(self._to_wake) - time.time())
self._to_run.extend(coro for t, coro in self._to_wake.items()
if t <= time.time())
有关更多详细信息,请参阅 David Beazley 的 this lecture,其中在现场观众面前构建了一个功能齐全的事件循环。 (不要因使用 yield from 而被推迟 - 较新的 async def 的工作方式完全相同。)