title: FastAPI依赖注入作用域与生命周期控制

date: 2025/04/08 00:02:10

updated: 2025/04/08 00:02:10

author: cmdragon

excerpt:

FastAPI框架中,依赖项的作用域决定了它们的创建和销毁时机,主要分为应用级和请求级两种。应用级依赖在整个应用生命周期内只初始化一次,适合长期保持的昂贵资源;请求级依赖在每个HTTP请求时创建新实例,适合需要频繁初始化的资源。通过yield语法可以实现请求级依赖的生命周期控制,确保资源在使用后正确释放。合理划分依赖项作用域和精确控制生命周期,能显著提升应用性能和资源利用率。

categories:

  • 后端开发
  • FastAPI

tags:

  • FastAPI
  • 依赖注入
  • 作用域
  • 生命周期控制
  • 应用级作用域
  • 请求级作用域
  • 资源管理


扫描二维码关注或者微信搜一搜:编程智域 前端至全栈交流与成长

探索数千个预构建的 AI 应用,开启你的下一个伟大创意

FastAPI依赖注入作用域与生命周期控制详解

1. 依赖项作用域基础概念

在FastAPI框架中,依赖项的作用域决定了它们的创建和销毁时机。就像图书馆里的公共设施(应用级)与个人借阅的书籍(请求级)的区别,不同作用域的依赖项适用于不同的使用场景。

作用域主要分为两种类型:

  1. 应用级作用域(Singleton):整个应用生命周期内只初始化一次
  2. 请求级作用域(Request):每个HTTP请求都会创建新的实例
from fastapi import Depends, FastAPI

app = FastAPI()

# 应用级依赖示例
class DatabasePool:
def __init__(self):
print("创建数据库连接池")
self.pool = "模拟连接池" db_pool = DatabasePool() @app.get("/data")
async def get_data(pool: str = Depends(lambda: db_pool.pool)):
return {"pool": pool}

2. 作用域划分实践技巧

2.1 应用级作用域配置

适合需要长期保持的昂贵资源,推荐在应用启动事件中初始化:

from contextlib import asynccontextmanager
from fastapi import FastAPI @asynccontextmanager
async def lifespan(app: FastAPI):
# 应用启动时初始化
app.state.db_pool = await create_db_pool()
yield
# 应用关闭时清理
await app.state.db_pool.close() app = FastAPI(lifespan=lifespan) @app.get("/items")
async def read_items(pool=Depends(lambda: app.state.db_pool)):
return {"pool": pool.status}

2.2 请求级作用域实现

使用yield语法实现请求级依赖的生命周期控制:

from fastapi import Depends
from sqlalchemy.ext.asyncio import AsyncSession async def get_db():
# 每个请求创建新会话
db_session = AsyncSession(bind=engine)
try:
yield db_session
finally:
# 请求结束后关闭会话
await db_session.close() @app.post("/users")
async def create_user(
user: UserSchema,
db: AsyncSession = Depends(get_db)
):
db.add(User(**user.dict()))
await db.commit()
return {"status": "created"}

3. 生命周期控制模式

3.1 初始化-使用-销毁流程

from typing import Generator
from fastapi import Depends class FileProcessor:
def __init__(self, filename):
self.file = open(filename, "r")
print(f"打开文件 {filename}") def process(self):
return self.file.read() def close(self):
self.file.close()
print("文件已关闭") def get_processor() -> Generator[FileProcessor, None, None]:
processor = FileProcessor("data.txt")
try:
yield processor
finally:
processor.close() @app.get("/process")
async def process_file(
processor: FileProcessor = Depends(get_processor)
):
content = processor.process()
return {"content": content[:100]}

4. 混合作用域实战案例

组合不同作用域的依赖项实现高效资源管理:

from fastapi import Depends, BackgroundTasks

# 应用级缓存
cache = {} # 请求级数据库连接
async def get_db():
... # 缓存依赖(应用级)
def get_cache():
return cache @app.post("/cached-data")
async def get_data(
db: AsyncSession = Depends(get_db),
cache: dict = Depends(get_cache),
bg: BackgroundTasks = Depends()
):
if "data" not in cache:
result = await db.execute("SELECT ...")
cache["data"] = result
bg.add_task(lambda: cache.pop("data", None), delay=3600)
return cache["data"]

5. 课后Quiz

问题1:请求级依赖的yield语句必须放在try/finally块中吗?

答案:不是必须,但推荐使用。finally块确保无论是否发生异常都会执行清理操作,避免资源泄漏

问题2:应用级依赖能否访问请求上下文?

答案:不能。应用级依赖在请求上下文创建之前就已经初始化,无法访问请求相关信息

6. 常见报错解决方案

错误1:RuntimeError: Dependency is not yield

原因:在异步依赖项中忘记使用yield语法

# 错误示例
async def get_db():
return Session() # 正确写法
async def get_db():
db = Session()
try:
yield db
finally:
db.close()

错误2:DependencyOveruseWarning

现象:频繁创建昂贵资源导致性能问题

解决:检查依赖项作用域是否合理,将数据库连接池等昂贵资源改为应用级作用域

错误3:ContextVariableNotFound

场景:在应用级依赖中尝试访问请求信息

处理:将需要请求信息的依赖改为请求级作用域,或通过参数传递所需数据

7. 环境配置与运行

安装依赖:

pip install fastapi uvicorn sqlalchemy python-dotenv

启动服务:

uvicorn main:app --reload --port 8000

测试端点:

curl http://localhost:8000/items
curl -X POST http://localhost:8000/users -H "Content-Type: application/json" -d '{"name":"John"}'

通过合理划分依赖项的作用域和精确控制生命周期,开发者可以显著提升FastAPI应用的性能和资源利用率。建议在实践中结合具体业务需求,通过性能测试确定最佳作用域配置方案。

余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长,阅读完整的文章:FastAPI依赖注入作用域与生命周期控制 | cmdragon's Blog

往期文章归档:

FastAPI依赖注入作用域与生命周期控制的更多相关文章

  1. Asp.Net Core 3.1学习-依赖注入、服务生命周期(6)

    1.前言 面向对象设计(OOD)里有一个重要的思想就是依赖倒置原则(DIP),并由该原则牵引出依赖注入(DI).控制反转(IOC)及其容器等概念.在学习Core依赖注入.服务生命周期之前,下面让我们先 ...

  2. 018-019 NET5_内置容器支持依赖注入+IServiceCollection的生命周期

    概念: DI依赖注入: IServiceCollection仅支持构造函数注入 什么是依赖注入? 如果对象A依赖对象B,对象B依赖对象C,就可以先构造对象C,然后传递给对象B,再把对象B传递给A.得到 ...

  3. Console app 里的依赖注入及其实例生命周期

    依赖注入是 ASP.NET Core 里的核心概念之一,我们平常总是愉快地在Startup类的ConfigureServices方法里往IServiceCollection里注册各种类型,以致有一些同 ...

  4. Bean 注解(Annotation)配置(2)- Bean作用域与生命周期回调方法配置

    Spring 系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of ...

  5. Bean XML 配置(2)- Bean作用域与生命周期回调方法配置

    系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of Contro ...

  6. ASP.NET Core中的依赖注入(1):控制反转(IoC)

    ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了"标准化&qu ...

  7. Spring之Bean的作用域与生命周期

    在前面博客中提到容器启动获得BeanDefinition对象中有一个scope 属性.该属性控制着bean对象的作用域.本章节介绍Bean的作用域及生命周期,了解bean是怎么来的又怎么没的. 一.B ...

  8. Spring学习3—控制反转(IOC)Spring依赖注入(DI)和控制反转(IOC)

    一.思想理解 Spring 能有效地组织J2EE应用各层的对象.不管是控制层的Action对象,还是业务层的Service对象,还是持久层的DAO对象,都可在Spring的 管理下有机地协调.运行.S ...

  9. 构件工具Maven----坐标、依赖、仓库、生命周期的简单学习

    这篇文章对Maven中几个比较重要的概念坐标.依赖.仓库.生命周期做一个简单的介绍. 1.关于Maven坐标 用来区别Maven世界中任何一个构件,Maven坐标的元素包括groupId.artifa ...

  10. Vue.js 子组件的异步加载及其生命周期控制

    前端开发社区的繁荣,造就了很多优秀的基于 MVVM 设计模式的框架,而组件化开发思想也越来越深入人心.这其中不得不提到 Vue.js 这个专注于 VM 层的框架. 本文主要对 Vue.js 组件化开发 ...

随机推荐

  1. 微服务实战系列(八)-网关springcloud gateway自定义规则-copy

    1. 场景描述 先说明下项目中使用的网关是:springcloud gateway, 因需要给各个网关服务系统提供自定义配置路由规则,实时生效,不用重启网关(重启风险大),目前已实现:动态加载自定义路 ...

  2. weixueyuan-Nginx集群9

    https://www.weixueyuan.net/nginx/colony/ LVS(Linux虚拟服务器)简介 LVS(Linux Virtual Server)是一个开源的负载均衡项目,是国内 ...

  3. struts2和Springmvc原理及比较

    一.拦截机制的不同 Struts2是类级别的拦截,每次请求就会创建一个Action,和Spring整合时Struts2的ActionBean注入作用域是原型模式prototype,然后通过setter ...

  4. JavaScript操作DOM元素的classList

    在JavaScript中,classList 是一个DOM元素属性,它提供了一组方法来添加.移除和切换元素的类名.classList 属性返回一个 DOMTokenList 集合,表示元素的类名. 这 ...

  5. 一款基于 .NET8 + Vue 开源、免费、跨平台的企业级在线考试系统

    前言 今天大姚给大家分享一款基于 .NET8 + Vue 开源.免费(AGPL-3.0开源协议).跨平台的企业级在线考试系统:XBLMS. 项目介绍 XBLMS是一款基于 .NET8 + Vue 开源 ...

  6. IDEA中Maven项目修改JSP后通过配置Tomcat实现立即生效

    参考: IntelliJ IDEA 的 Project Structure 窗口中的 Artifacts 勾选 Include in project build IDEA中Facets和Artifac ...

  7. RabbitMQ(五)——发布订阅模式

    RabbitMQ系列 RabbitMQ(一)--简介 RabbitMQ(二)--模式类型 RabbitMQ(三)--简单模式 RabbitMQ(四)--工作队列模式 RabbitMQ(五)--发布订阅 ...

  8. .NET程序员AI开发基座:Microsoft.Extensions.AI

    大家好,我是Edison. 微软在2024年11月就发布了新的AI核心库Microsoft.Extensions.AI,虽然目前还是一个预览版,但其可以大大简化我们的AI集成和开发工作. Micros ...

  9. SpringBoot+Mybatis-Plus使用多数据源

    常见的使用Mybatis-Plus配置多数据源方式有两种:一种是通过java config的方式手动配置两个数据源,另一种方式便是使用 dynamic-datasource-spring-boot-s ...

  10. Deepin搭建git仓库服务gogs,debian也可用

    我尝试了gitlab.gitblit搭建均失败,deepin版本20.03 1. 步骤 访问gogs官网下载&安装页面 数据库(选择以下一项): MySQL:版本 >= 5.7. Pos ...