实际信息:
从 Python 3.7 开始 asyncio.create_task(coro) 高级函数 was added 用于此目的。
您应该使用它来代替从 coroutimes 创建任务的其他方式。但是,如果您需要从任意等待创建任务,您应该使用asyncio.ensure_future(obj)。
旧信息:
ensure_future 与 create_task
ensure_future 是一种从coroutine 创建Task 的方法。它根据参数以不同的方式创建任务(包括将create_task 用于协程和类似未来的对象)。
create_task 是AbstractEventLoop 的抽象方法。不同的事件循环可以不同的方式实现这个功能。
您应该使用ensure_future 来创建任务。仅当您要实现自己的事件循环类型时,您才需要 create_task。
更新:
@bj0 在这个话题上指着Guido's answer:
ensure_future() 的意义在于,如果你有一些东西可以
要么是协程,要么是Future(后者包括Task,因为
那是Future) 的子类,你希望能够调用一个方法
仅在Future 上定义的它(可能是唯一有用的
例如cancel())。当它已经是Future(或Task)时
什么也没做;当它是一个协程时,它包装它在Task中。
如果你知道你有一个协程并且你希望它被调度,
要使用的正确 API 是 create_task()。唯一应该的时候
调用ensure_future() 是在您提供 API 时(像大多数
asyncio 自己的 API) 接受协程或 Future 和
你需要做一些事情,需要你有一个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')
# Now you want to start long_operation, but you don't want to wait it finised:
# long_operation should be started, but second msg should be printed immediately.
# Create task to do so:
task = asyncio.ensure_future(long_operation())
await msg('second')
# Now, when you want, you can await task finised:
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() 来感受不同。