Python asyncio中Task封装协程的核心机制与用法详解
本文深入解析Python中Task如何封装协程。Task作为Future子类,用于追踪协程状态并加入事件循环。重点介绍asyncio.create_task()的用法、Task延迟执行特性,以及通过asyncio.wait或gather调度多个并发任务的完整流程与代码示例。
说明
Task是Future类的子类,它本质上是对协程对象的封装。通过将多个Task实例添加到循环调度列表中,系统可以等待并调度它们执行。
Task对象具备跟踪任务运行状态的功能。作为Future的子类,它为异步编程中最终结果的获取提供了支持,同时Task类自身也具备状态处理能力。
将协程封装为Task后,需将其加入队列等待调用。Task在刚创建时处于未执行状态,只有当代码遇到await关键字并等待该Task时,它才会真正开始执行。
实例
import asyncio
async def func():
print(1)
await asyncio.sleep(2)
print(2)
return "返回值"
async def main():
print("main开始")
# 创建协程,将协程封装到Task对象中并添加到事件循环的任务列表中,等待事件循环去执行(默认是就绪状态)。
# 在调用
task_list = [
asyncio.create_task(func(), name="n1"),
asyncio.create_task(func(), name="n2")
]
print("main结束")
# 当执行某协程遇到IO操作时,会自动化切换执行其他任务。
# 此处的await是等待所有协程执行完毕,并将所有协程的返回值保存到done
# 如果设置了timeout值,则意味着此处最多等待的秒,完成的协程返回值写入到done中,未完成则写到pending中。
done, pending = await asyncio.wait(task_list, timeout=None)
print(done, pending)
asyncio.run(main())
知识点扩展:
Task 概念及用法
- Task是Python中与事件循环交互的主要方式之一。
创建Task意味着将协程封装为Task实例,并追踪其运行或完成状态,以便后续获取协程的执行结果。
- Task的核心作用在于向事件循环中添加多个并发任务。
具体实现上,通过调用asyncio.create_task()创建Task,使协程对象加入事件循环,从而等待被调度执行。
注意:Python 3.7及以后版本支持asyncio.create_task(),在此之前的版本需使用loop.create_task(),开发时需确保代码对不同Python版本的兼容性。
- 需要指出的是,协程封装为Task后不会立即启动,只有当某段代码await该Task时,它才会被执行。
当多个Task被加入task_list时,在添加过程中Task不会执行。必须使用await asyncio.wait()或await asyncio.gather()将Task对象加入事件循环,才能使其异步执行。
- 一般在开发中,常用的写法是这样的:
-- 先创建task_list空列表; -- 然后用asyncio.create_task()创建Task; -- 再把Task对象加入task_list; -- 最后使用await asyncio.wait或await asyncio.gather将Task对象加入事件循环中异步执行。
注意:创建Task对象时,除了可以使用asyncio.create_task()之外,还可以用最低层级的loop.create_task()或asyncio.ensure_future(),它们都可以用来创建Task对象,其中关于ensure_future相关内容本文接下来会一起讲。
Task 用法代码示例:
import asyncio
import arrow
def current_time():
'''
获取当前时间
:return:
'''
cur_time = arrow.now().to('Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss')
return cur_time
async def func(sleep_time):
func_name_suffix = sleep_time # 使用 sleep_time(函数 I/O 等待时长)作为函数名后缀,以区分任务对象
print(f"[{current_time()}] 执行异步函数 {func.__name__}-{func_name_suffix}")
await asyncio.sleep(sleep_time)
print(f"[{current_time()}] 函数 {func.__name__}-{func_name_suffix} 执行完毕")
return f"【[{current_time()}] 得到函数 {func.__name__}-{func_name_suffix} 执行结果】"
async def run():
task_list = []
for i in range(5):
task = asyncio.create_task(async_func(i))
task_list.append(task)
done, pending = await asyncio.wait(task_list, timeout=None)
for done_task in done:
print((f"[{current_time()}] 得到执行结果 {done_task.result()}"))
def main():
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
if __name__ == '__main__':
main()
到此这篇关于python中Task封装协程的知识点总结的文章就介绍到这了,更多相关python中Task封装协程内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













