为什么FastAPI依赖中yield返回的SQLAlchemy Session超出作用域会自动关闭?
你对普通生成器的执行逻辑的理解是正确的:如果没有外部逻辑主动驱动生成器完成后续执行,生成器在yield处暂停后,若上下文被直接回收,finally代码块确实不会触发。但FastAPI的依赖注入系统对带yield的依赖有专门的生命周期管理逻辑,保证了finally必然执行:
- 当请求进入需要用到
get_db依赖的路由时,FastAPI会首先迭代这个异步生成器一次,获取到yield返回的数据库会话实例,注入到路由函数中供业务逻辑使用。 - 无论请求后续是正常处理完成、中途抛出业务异常、还是客户端主动断开连接导致请求中断,FastAPI都会在请求生命周期结束时,主动调用该生成器的
aclose方法。
当生成器的aclose方法被调用时,会在当前yield暂停的位置抛出GeneratorExit异常,该异常会被try语句捕获,进而触发finally代码块中的db.close()逻辑,保证会话资源必然被释放。
你可以用下面的极简代码验证这个逻辑:
import asyncio async def test_depend(): print("资源初始化") try: yield "返回的资源" finally: print("资源清理逻辑执行") async def main(): gen = test_depend() res = await gen.__anext__() print(f"业务逻辑使用资源: {res}") # 对应FastAPI在请求结束时的处理 await gen.aclose() asyncio.run(main())
运行后会看到资源清理逻辑执行的输出,和FastAPI内部的处理逻辑一致。
内容的提问来源于stack exchange,提问作者j_krl
相关产品推荐
相关产品推荐

