nursery.child_tasks与nursery.parent_task父子任务关系
Trio 中父任务与子任务的关系及取消行为
在 Trio 中,任务(Task)之间的父子关系是理解结构化并发的关键。当你使用
async with trio.open_nursery() as nursery创建一个 nursery 时,会建立明确的父子任务关系:一、父任务与子任务的关系
1. 基本概念
- 父任务:创建 nursery 的任务(即执行async with trio.open_nursery()的任务)
- 子任务:通过nursery.start_soon()启动的任务
- nursery:管理子任务的生命周期,确保所有子任务完成后才允许父任务继续
2. 关键特性
- 结构化并发:子任务的生命周期被限制在 nursery 的上下文中
- 错误传播:如果子任务抛出未处理的异常,nursery 会:- 取消所有其他子任务
- 将异常传播给父任务
 
- 资源管理:nursery 确保所有子任务完成(或被取消)后才退出上下文
二、取消父任务的行为
如果父任务被取消(例如通过其取消范围),会发生以下连锁反应:
- 父任务的取消范围被触发
- 这会导致 nursery 的取消范围也被触发
 
- 所有子任务被取消
- 子任务会收到Cancelled异常
- 子任务有机会执行清理代码(try/finally块)
 
- 子任务会收到
- 等待所有子任务完成
- nursery 会等待所有子任务完成清理工作
 
- 父任务继续执行
- 一旦所有子任务完成,父任务会继续执行取消逻辑
 
三、代码示例
以下代码演示了取消父任务对子任务的影响:
python
运行
import trio
async def child_task(delay, name):
    try:
        print(f"{name} 开始执行")
        await trio.sleep(delay)
        print(f"{name} 正常完成")
    except trio.Cancelled:
        print(f"{name} 被取消,正在清理...")
        await trio.sleep(0.5)  # 模拟清理工作
        print(f"{name} 清理完成")
        raise  # 必须重新抛出异常以表明任务已取消
async def parent_task():
    print("父任务开始")
    async with trio.open_nursery() as nursery:
        print("创建子任务")
        nursery.start_soon(child_task, 5, "子任务1")
        nursery.start_soon(child_task, 10, "子任务2")
        
        print("父任务即将被取消")
        # 取消父任务(通常由外部触发)
        nursery.cancel_scope.cancel()
        
        print("父任务等待子任务完成清理...")
        # 控制流会在这里阻塞,直到所有子任务完成或被取消
    
    print("父任务继续执行")
trio.run(parent_task)输出示例:
plaintext
父任务开始
创建子任务
父任务即将被取消
父任务等待子任务完成清理...
子任务1 开始执行
子任务2 开始执行
子任务1 被取消,正在清理...
子任务2 被取消,正在清理...
子任务1 清理完成
子任务2 清理完成
父任务继续执行四、重要注意事项
- 
子任务必须处理取消
 - 子任务应通过try/finally或async with确保资源正确清理
- 未处理的取消可能导致资源泄漏
 
- 子任务应通过
- 
取消是协作式的
 - Trio 的取消是协作式的,子任务需要检查取消请求
- 使用await trio.sleep()或其他检查点函数使任务可取消
 
- 
异常传播
 - 如果子任务抛出异常,nursery 会取消所有其他子任务
- 父任务可以捕获这些异常并进行处理
 
- 
使用shield防止意外取消
 - 如果需要保护某些代码不被取消,可以使用shield:python运行with trio.CancelScope(shield=True): # 这里的代码不会被外部取消
 
- 如果需要保护某些代码不被取消,可以使用
五、总结
取消父任务会导致:
- 父任务的取消范围被触发
- 所有子任务收到取消请求
- 子任务有机会执行清理代码
- 父任务等待所有子任务完成清理
- 父任务继续执行(或传播取消异常)
这种设计确保了资源的正确清理和结构化并发,是 Trio 安全性的核心特性之一。
 
                    
                     
                    
                 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号 
