新闻中心

FastAPI 应用启动后执行一次性任务的正确姿势

2025-11-01
浏览次数:
返回列表

FastAPI 应用启动后执行一次性任务的正确姿势

本文详细介绍了如何使用 fastapi 的 lifespan 事件结合 asynccontextmanager 在应用启动后、处理任何请求之前执行一次性初始化任务。通过此机制,开发者可以确保数据库连接、缓存预加载等操作在服务可用时已完成,同时避免阻塞服务器启动过程。

理解应用启动时的初始化需求

在构建基于 FastAPI 的 Web 服务时,我们经常需要在应用程序启动后、开始处理用户请求之前执行一些初始化操作。这些操作可能包括:

  • 加载配置数据
  • 建立数据库连接池
  • 预加载缓存数据
  • 启动后台任务或消费者
  • 执行其他一次性设置逻辑

直接在 if __name__ == "__main__": 块中调用这些函数,如果放在 uvicorn.run(app) 之前,会阻塞服务器启动,导致服务无法及时响应;如果放在 uvicorn.run(app) 之后,则根本不会被执行,因为 uvicorn.run(app) 是一个阻塞调用,会一直运行直到服务器关闭。因此,我们需要一个机制,让 FastAPI 框架自身来管理这些启动事件。

FastAPI 的 Lifespan 事件管理

FastAPI 提供了 lifespan 事件管理机制,它基于 Python 的 contextlib.asynccontextmanager,允许开发者定义在应用启动和关闭时执行的异步代码。这是处理一次性初始化任务的官方推荐方式。

lifespan 的核心思想是定义一个异步上下文管理器。当应用启动时,上下文管理器会执行 yield 语句之前的代码;当应用准备好接收请求时,它会 yield 控制权,此时服务开始处理请求;当应用关闭时,它会执行 yield 语句之后(即上下文退出时)的代码,用于资源清理。

示例:在 FastAPI 启动后初始化数据

假设我们有一个需求,在 FastAPI 应用启动后,需要执行一个耗时操作(例如,模拟数据加载),然后初始化一个全局变量 DATA。

import time
import uvicorn
from fastapi import FastAPI
from contextlib import asynccontextmanager

# 全局变量,用于存储初始化后的数据
DATA = {"value": ""}

def create_data():
    """
    模拟一个耗时的初始化函数,用于在应用启动时加载数据。
    """
    print("正在执行 create_data()...")
    time.sleep(2)  # 模拟耗时操作,例如从数据库加载数据或进行复杂的计算
    DATA["value"] = "Hello World!"
    print("create_data() 执行完毕。")

@asynccontextmanager
async def lifespan(app: FastAPI):
    """
    FastAPI 应用的生命周期管理器。
    在应用启动时执行 create_data(),并在应用关闭时执行清理操作(如果需要)。
    """
    # --- 应用启动时执行的代码 ---
    create_data()  # 在这里调用我们的初始化函数
    print("FastAPI 应用已启动,准备接收请求。")
    yield  # 应用在此处开始接收请求,yield 之前的代码在启动前完成
    # --- 应用关闭时执行的代码 ---
    print("FastAPI 应用正在关闭。")
    # 可以在这里执行清理操作,例如关闭数据库连接、释放资源等
    DATA["value"] = "" # 清理数据,模拟资源释放
    print("清理工作完成。")

# 将 lifespan 事件管理器传递给 FastAPI 应用
app = FastAPI(lifespan=lifespan)

@app.get("/")
def get_root():
    """
    一个简单的 GET 接口,返回 DATA 中存储的值。
    """
    return DATA

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

代码解析

  1. from contextlib import asynccontextmanager: 导入 asynccontextmanager 装饰器,它是创建异步上下文管理器的关键。
  2. DATA = {"value": ""}: 定义一个全局字典,用于存储初始化后的数据。
  3. def create_data():: 这是一个普通函数,包含了我们希望在应用启动时执行的逻辑。这里模拟了数据加载的耗时操作。
  4. @asynccontextmanager: 这个装饰器将 lifespan 异步生成器函数转换为一个异步上下文管理器。
  5. async def lifespan(app: FastAPI)::
    • 这个异步函数是 lifespan 事件的核心。它接收 FastAPI 应用实例作为参数。
    • create_data(): 在 yield 语句之前,create_data() 函数会被调用。这意味着在 FastAPI 应用开始处理任何 HTTP 请求之前,create_data() 会先执行并完成。
    • yield: 这是上下文管理器的关键点。当执行到 yield 语句时,lifespan 函数会暂停,并将控制权交还给 FastAPI。此时,FastAPI 应用正式启动,可以开始接收并处理客户端请求。
    • yield 之后的代码会在应用关闭时执行。这提供了一个方便的钩子来执行清理工作,例如关闭数据库连接、释放内存等。
  6. app = FastAPI(lifespan=lifespan): 在创建 FastAPI 应用实例时,通过 lifespan 参数将我们定义的 lifespan 上下文管理器传递进去。FastAPI 会在内部管理这个生命周期事件。
  7. uvicorn.run(app): 正常启动 Uvicorn 服务器。此时,lifespan 中 yield 之前的代码(即 create_data())会先执行。

运行效果

当你运行上述代码时,你会观察到以下输出顺序:

短影AI 短影AI

长视频一键生成精彩短视频

短影AI 170 查看详情 短影AI
正在执行 create_data()...
create_data() 执行完毕。
FastAPI 应用已启动,准备接收请求。
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [xxxxx] using statreload
INFO:     Started server process [xxxxx]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

然后,如果你访问 http://localhost:8000,你会得到 {"value": "Hello World!"},这证明 create_data() 已经成功执行并更新了 DATA 变量。

当你按下 CTRL+C 停止服务器时,你会看到:

INFO:     Shutting down
FastAPI 应用正在关闭。
清理工作完成。
INFO:     Finished server process [xxxxx]
INFO:     Stopped reloader process [xxxxx]

这表明 yield 之后的清理代码也得到了正确执行。

注意事项

  • 异步操作: 如果你的初始化函数 create_data 内部包含异步操作(例如 await 数据库查询、网络请求),那么 create_data 函数本身也应该是一个 async def 函数,并且在 lifespan 中调用时需要使用 await create_data()。
  • 错误处理: 在 lifespan 的启动阶段(yield 之前)如果发生未捕获的异常,FastAPI 应用将无法启动。因此,建议对关键的初始化逻辑进行适当的错误处理,例如使用 try...except 块。
  • 资源清理: yield 之后的代码块是执行资源清理的理想位置。确保在这里释放所有在启动阶段获取的资源,以避免内存泄漏或资源耗尽。
  • 全局状态管理: 尽管在 lifespan 中修改全局变量是可行的,但对于更复杂的应用,考虑使用依赖注入(Dependency Injection)或 FastAPI 的 app.state 来管理应用级别的状态,以提高代码的可维护性和可测试性。app.state 允许你在应用实例上直接存储和访问状态。

总结

通过 FastAPI 的 lifespan 事件结合 asynccontextmanager,我们可以优雅且高效地管理应用的启动和关闭事件。这种机制确保了在服务正式对外提供前,所有必要的初始化工作都能顺利完成,并且在服务关闭时能够进行必要的资源清理。掌握 lifespan 是构建健壮和可维护的 FastAPI 应用的关键一环。

以上就是FastAPI 应用启动后执行一次性任务的正确姿势的详细内容,更多请关注其它相关文章!


# 放在  # reddit seo  # 白云区关键词排名怎么选  # 微网站建设请示  # 软文营销推广投放平台  # 万城建设网站  # 烟台网站建设教学视频  # 怎么在国外seo  # 长春关键词排名推广  # 全站推广新出的整合营销  # 新蔡营销推广  # 当你  # python  # 全局变量  # 你会  # 在这里  # 自定义  # 这是  # 加载  # 启动时  # 管理器  # ai  # app 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: qq邮箱日历功能怎么用_创建日程与会议邀请的技巧  Vue.js 图片显示异常排查:理解应用挂载范围与DOM ID唯一性  火狐浏览器占用内存高卡顿怎么办 火狐浏览器性能优化设置技巧  J*a里如何实现线程安全的懒加载单例_懒加载单例实现方法解析  Golang如何使用net/url解析URL_Golang URL解析与处理方法  outlook中文官网入口地址 outlook官方中文版直达首页链接  Go语言中Map值调用指针接收器方法的限制与应对  蛙漫安全无毒 官方认证的绿色入口  QQ邮箱电脑版登录入口_QQ邮箱官方网站登录平台  拷贝漫画电脑版官网入口 拷贝漫画(PC版)在线直达  mysql如何设置表访问权限_mysql表访问权限配置  谷歌邮箱网页版官方页面入口 谷歌邮箱网页端快速访问  Composer如何在生产环境安全地执行composer update  Windows10怎么开启存储感知 Windows10系统设置自动清理临时文件释放C盘空间【教程】  QQ邮箱登录首页官网地址2026 QQ邮箱官方网页入口  树莓派传感器触发:通过Twilio API发送WhatsApp消息教程  Go RPC HTTP服务正确实现与常见陷阱解析  如何使用Go和Martini动态服务解码后的图片  京东京造J1和网易云音乐氧气真无线有什么不同_国产电商蓝牙耳机音质对比  sublime怎么格式化代码_sublime代码美化与一键排版插件配置  俄罗斯方块最新版入口 俄罗斯方块在线玩官网入口  sublime怎么覆盖插件的默认快捷键_sublime快捷键优先级与设置  Win10文件资源管理器“此电脑”分组怎么关 Win10恢复经典视图【技巧】  J*a里如何实现订单支付与库存同步功能_支付库存同步项目开发方法说明  qq浏览器打开空白页怎么办 qq浏览器启动后显示白屏的解决教程  中兴Axon42Ultra怎样在文件App筛图_iPhone中兴Axon42Ultra文件App筛图【图片筛选】  c++如何实现单例设计模式_c++线程安全的单例模式写法  html怎么运行外部js文件中的函数_运html外js文件函数法【技巧】  AO3中文官网链接_AO3网页版稳定镜像站  CSS Grid如何控制元素对齐_align-items与justify-items组合使用  C++的std::forward_list怎么用_C++ STL中单向链表容器的特点与应用  C++ vector二维数组定义_C++ vector of vector用法  AngularJS $http POST请求数据传递与Go后端接收实践  ArchiveofOurOwn小说阅读-ArchiveofOurOwn同人作品访问链接  如何在Promise链中有效终止错误处理后的执行  快手极速版在线观看 官方网页版登录地址  快手网页版在线登录 快手网页版官网入口快速访问  Golang如何实现容器化日志收集与分析_Golang容器日志收集分析方法  css元素hover动画延迟生效怎么办_使用animation-delay调整触发时间  wps文字怎么插入目录并自动更新_wps文字如何插入目录并自动更新方法  天眼查怎么看公司融资情况 天眼查企业融资历史查询步骤【攻略】  J*a递归快速排序中静态变量导致数据累积的陷阱与解决方案  Surface怎么安装系统 微软Surface Pro U盘重装win11教程  b站怎么删除评论_b站评论管理与删除操作  动漫岛观看全网网 动漫岛在线正版动漫入口  Google翻译怎么语音输入_Google翻译语音输入功能使用与设置方法  如何在CSS中使用浮动制作导航栏_float实现水平菜单  如何优雅地扩展SprykerGlue后端API授权逻辑,使用spryker/glue-backend-api-application-authorization-connector-extension  CSS图片焦点样式实现教程:理解与应用tabindex属性  Django表单提交验证失败后保持字段值不刷新 

搜索