You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI中Depends结合生成器为何可充当上下文管理器?

问题:FastAPI中Depends处理生成器依赖的finally块执行时机疑问

我在学习FastAPI教程时遇到如下代码:

def get_db():
    try:
        db = SessionLocal()
        yield db
    finally:
        print("from finally block")
        db.close()
@app.get("/")
async def read_all(db: Session = Depends(get_db)):
    res = db.query(models.Todos).all()
    print("from endpoint")
    return res

执行结果为:

INFO:     127.0.0.1:39088 - "GET /openapi.json HTTP/1.1" 200 OK
from endpoint
INFO:     127.0.0.1:39088 - "GET / HTTP/1.1" 200 OK
from finally block

发现Depends(get_db)的行为类似上下文管理器,from finally block直到read_all端点执行完毕才输出。但测试普通生成器:

class SomeDependency:
    def __enter__(self):
        print("entering")
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("exited")

def hello():
    try:
        yield SomeDependency()
    finally:
        print("yolo")

if __name__ == "__main__":
   next(hello())

调用next(hello())后,finally块会立即执行。为何get_db的finally块传入Depends后不会立即执行?


解答

核心原因是FastAPI对生成器类型的依赖做了专门的生命周期管理,和普通生成器的调用逻辑完全不同:

  1. FastAPI接管了生成器的完整生命周期
    当你把生成器函数传给Depends时,FastAPI会将其作为请求级别的上下文管理器来使用:

    • 首先执行生成器到yield语句,把生成的数据库会话对象注入到端点函数中;
    • 等端点函数执行完成(包括响应已经返回给客户端),FastAPI会主动调用生成器的close()方法,这时候生成器才会进入finally块,执行数据库连接关闭的逻辑。
      这种设计是为了保证资源(比如数据库连接)在整个请求周期内可用,请求结束后再统一清理。
  2. 普通生成器的调用触发了即时回收
    你测试的next(hello())中,生成器对象是临时创建的,调用next()拿到yield的值后,这个生成器没有被任何变量引用,Python的垃圾回收机制会立即销毁它。生成器被销毁时会自动调用close()方法,从而触发finally块执行。
    如果修改代码,让生成器被持有引用,finally块就不会立即执行:

    def hello():
        try:
            yield SomeDependency()
        finally:
            print("yolo")
    
    if __name__ == "__main__":
        gen = hello()
        next(gen)
        # 此时finally不会执行
        gen.close()  # 调用close后才会打印yolo
    

简单来说,FastAPI为了实现依赖的“请求创建、请求结束销毁”的生命周期,封装了生成器的执行逻辑;而普通生成器在无引用时会被即时回收,提前触发finally块。


内容的提问来源于stack exchange,提问作者Halcyon Abraham Ramirez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 12:05:42