asyncio.ensure_future()
用于调度协程(coroutine)或其他可等待对象(awaitable)的执行。它的核心功能是确保一个可等待对象最终被包装成一个 asyncio.Task
对象,并安排它在事件循环中运行。
asyncio.ensure_future
的主要作用
调度执行:当你有一个协程函数,但不想立即
await
它(因为await
会阻塞当前任务直到该协程完成),你可以使用asyncio.ensure_future()
来把它提交给事件循环,让它在后台并发执行。统一对象类型:这个函数非常灵活,它可以接受多种类型的输入:
- 如果是协程(coroutine):它会调用
loop.create_task()
将协程包装成一个Task
对象。 这个Task
会被安排在事件循环中执行。 - 如果是
Future
或Task
对象:它会直接返回该对象,不做任何改变。 因为Task
本身就是Future
的子类。 - 如果是其他可等待对象(awaitable):它会将其包装在一个
Task
中,该任务会await
这个对象。
这个特性使得
ensure_future()
在编写库或API时特别有用,因为你无需关心传入的到底是一个协程还是一个已经存在的Task
,ensure_future()
都能确保你得到一个可以操作的Future
对象(比如用于取消操作)。- 如果是协程(coroutine):它会调用
asyncio.ensure_future
vs asyncio.create_task
在现代 Python (3.7+) 中,asyncio.create_task()
是创建和调度任务的首选方式。 了解它们之间的区别很重要:
asyncio.create_task(coro)
:- 目的明确:专门用于从一个协程创建并调度一个
Task
。 它是更高级别的API,推荐在应用代码中使用。 - 输入限制:它的参数只能是协程对象。
- 可读性好:函数名清晰地表达了其意图——创建一个任务。
- 目的明确:专门用于从一个协程创建并调度一个
asyncio.ensure_future(awaitable)
:- 功能更广泛:如上所述,它可以接受协程、
Future
、Task
或其他可等待对象。 - 向后兼容:
create_task()
是在 Python 3.7 中引入的。在之前的版本中,ensure_future()
是创建任务的主要方式。 - 适用场景:当你需要编写一个能同时处理协程和
Future
对象的通用函数时,ensure_future()
更加合适。
- 功能更广泛:如上所述,它可以接受协程、
总结:在 Python 3.7 及更高版本中,如果你明确知道要从一个协程创建一个任务,应该优先使用 asyncio.create_task()
。 只有在需要兼容旧版本或处理不确定是协程还是 Future
的输入时,才需要使用 asyncio.ensure_future()
。
如何使用 asyncio.ensure_future
下面是一个代码示例,展示了如何使用 ensure_future()
来并发执行任务。
1 | import asyncio |
运行结果分析:
main
函数开始执行,task1
和task2
通过asyncio.ensure_future()
被调度。它们会立即开始并发运行,而不是一个接一个。- 程序打印 “任务已调度…”,并等待1秒。在此期间,
task1
和task2
都在后台执行它们的asyncio.sleep()
。 await task1
和await task2
会等待各自的任务完成。由于它们是并发执行的,总耗时取决于最长的那个任务(任务B,3秒),而不是两个任务时间的总和(2 + 3 = 5秒)。- 最终的总耗时约等于3秒,证明了并发执行的效率。
- 示例也验证了当
ensure_future
的参数已经是Task
时,它会返回完全相同的对象。