Python 异步编程 -- asyncio.create_task() vs asyncio.ensure_future()

asyncio 中,create_task()ensure_future() 都可以用来安排一个协程(coroutine)的执行,并将其包装成一个任务(Task)。然而,它们之间存在一些关键的区别,了解这些区别有助于编写更清晰、更现代的异步代码。

简单来说:在现代 Python (3.7+) 中,你应该优先使用 asyncio.create_task()


asyncio.create_task()

create_task() 是在 Python 3.7 中引入的,作为创建和安排协程执行的推荐方式。

作用

  • 明确的意图:其名称清晰地表明了它的作用——创建一个 Task
  • 高层 API:它是一个简单直接的高层函数。
  • 参数:它只接受一个协程对象作为参数。
  • 返回值:总是返回一个 asyncio.Task 对象。

使用场景

  • 在任何需要将协程作为后台任务并发执行的应用代码中。这是现代 asyncio 编程的标准做法。

代码示例

import asyncio

async def my_coroutine():
    print("Coroutine is running in the background")
    await asyncio.sleep(1)
    print("Coroutine has finished")

async def main():
    print("Main function started")
    # 使用 create_task 创建一个后台任务
    task = asyncio.create_task(my_coroutine())
    # main 函数可以继续执行其他工作,而不需要等待 task 完成
    print("Main function continues its work")
    await asyncio.sleep(2) # 等待足够长的时间以确保任务完成
    print("Main function finished")

asyncio.run(main())

asyncio.ensure_future()

ensure_future() 是一个更早(从 Python 3.4.4 开始)且更底层的函数。

作用

  • 兼容性:它的主要作用是确保你得到一个 Future 对象。
  • 参数:它可以接受一个协程、一个 Future 对象或一个 Task 对象。
  • 返回值
    • 如果传入一个协程,它会调用 loop.create_task() 来创建一个 Task 并返回它(行为类似于 create_task())。
    • 如果传入一个 FutureTask 对象,它会原封不动地返回该对象。

这个“确保”的特性使得它在编写需要同时处理协程和 Future 对象的库代码时非常有用。

使用场景

  • 兼容旧版本 Python:在 Python 3.7 之前,这是创建任务的唯一官方推荐方式。
  • 编写库代码:当你的函数需要接受一个“可等待”对象,但不确定它是一个协程还是一个已经存在的 Task/Future 时,ensure_future() 可以方便地进行统一处理。

代码示例

import asyncio

async def my_coroutine():
    return "Done"

async def main():
    # 1. 传入协程
    task1 = asyncio.ensure_future(my_coroutine())
    print(f"Is task1 a Task? {isinstance(task1, asyncio.Task)}")

    # 2. 传入Task
    task2 = asyncio.create_task(my_coroutine())
    task3 = asyncio.ensure_future(task2)
    
    # task2 和 task3 是同一个对象
    print(f"Are task2 and task3 the same object? {task2 is task3}")

asyncio.run(main())

# 输出:
# Is task1 a Task? True
# Are task2 and task3 the same object? True

主要区别总结

特性asyncio.create_task()asyncio.ensure_future()
引入版本Python 3.7Python 3.4.4
API 级别高层底层
意图清晰:创建新任务确保得到一个 Future/Task
参数类型仅协程 (Coroutine)协程、Future 或 Task
返回值总是创建一个新的 Task如果参数是 Future/Task,则直接返回

结论与最佳实践

  • 对于应用开发者:在你的项目中使用 Python 3.7 或更高版本时,始终使用 asyncio.create_task()。它的意图更明确,是社区推荐的最佳实践。

  • 对于库开发者:只有在你需要兼容 Python 3.6 及更早版本,或者你需要编写一个能同时接受协程和 Future 对象的灵活函数时,才考虑使用 asyncio.ensure_future()

简单来说,create_task 是为“做某事”而设计的,而 ensure_future 是为“确保某物是某种类型”而设计的。在日常开发中,我们绝大多数时候都属于前者。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nvd11

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值