实际信息:
从Python 3.7开始,为此目的添加了高级函数asyncio.create_task(coro)
。
您应该使用它来代替从协程创建任务的其他方式。但是,如果您需要从任意可等待对象创建任务,则应使用asyncio.ensure_future(obj)
。
旧信息:
ensure_future
与create_task
ensure_future
是一种从协程
创建任务
的方法。它根据参数以不同的方式创建任务(包括使用create_task
来处理协程和类似于future的对象)。
create_task
是AbstractEventLoop
的一个抽象方法。不同的事件循环可以以不同的方式实现此函数。
您应该使用ensure_future
来创建任务。只有当您要实现自己的事件循环类型时,才需要使用create_task
。
更新:
@bj0指出了Guido在这个主题上的回答:
ensure_future()
的作用是,如果你有一个既可以是协程也可以是 Future
(后者包括 Task
,因为它是 Future
的子类)的东西,并且你想要调用一个仅在 Future
上定义的方法(可能是唯一有用的例子是 cancel()
)。当它已经是一个 Future
(或 Task
)时,这个函数不会执行任何操作;当它是一个协程时,它会将其 封装 在一个 Task
中。
如果你知道自己有一个协程并希望对其进行调度,则应使用正确的 API create_task()
。只有在提供一个接受协程或 Future
的 API(像大多数 asyncio 自己的 API 一样)并且需要对其进行一些需要 Future
的操作时才应该调用 ensure_future()
。
稍后:
最后,我仍然认为
ensure_future()
是一个适当模糊的名称,用于很少需要的功能。在从协程创建任务时,应该使用名为
loop.create_task()
的函数。也许应该为其提供一个别名
asyncio.create_task()
?
这令我感到惊讶。一直以来我使用ensure_future
的主要动机是它比循环的成员create_task
更高级(讨论contains中有添加asyncio.spawn
或asyncio.create_task
等想法)。我还可以指出,在我看来,使用可以处理任何Awaitable
而不仅仅是协程的通用函数非常方便。
然而,Guido的回答很清晰:"在从协程创建任务时,应该使用名为loop.create_task()
的函数"
什么时候应该将协程封装在任务中?
将协程包装在任务中是一种在后台启动该协程的方法。以下是示例:
import asyncio
async def msg(text):
await asyncio.sleep(0.1)
print(text)
async def long_operation():
print('long_operation started')
await asyncio.sleep(3)
print('long_operation finished')
async def main():
await msg('first')
task = asyncio.ensure_future(long_operation())
await msg('second')
await task
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
输出:
first
long_operation started
second
long_operation finished
你可以将
asyncio.ensure_future(long_operation())
替换为
await long_operation()
,以感受差异。
create_task
,但通常情况下你不需要它:https://github.com/python/asyncio/issues/477#issuecomment-268709555 - bj0ensure_future
会自动将创建的Task
添加到主事件循环中吗? - AlQuemistloop
关键字参数指定其他事件循环(请参阅 ensure_future 签名)。 - Mikhail Gerasimovmsg()
函数内使用await
关键字,以便在第二次调用时将控制权返回给事件循环。一旦事件循环接收到控制权,就能够开始执行long_operation()
函数。这样可以演示如何使用ensure_future
并发地启动协程以与当前的执行流同时运行。 - Mikhail Gerasimovlong_operation finished
,因为main()
(以及整个事件循环)在long_operation()
任务之前就已经结束了。我猜在 Jupyter 中运行脚本可能不是这种情况,但无论如何,await task
的想法是我们需要等待任务完成。 - Mikhail Gerasimov