当前位置: 首页 > news >正文

python之Starlete的lifespan使用

一、lifespan 是什么?

lifespan是 Starlette 提供的应用生命周期管理机制,用于定义应用启动(startup)和关闭(shutdown)时需要执行的操作,比如:

  • 启动时:初始化数据库连接池、加载配置文件、启动定时任务、创建缓存实例;
  • 关闭时:关闭数据库连接、释放资源、保存临时数据、停止定时任务。

它替代了 Starlette 旧版本中的on_startup/on_shutdown钩子,是当前推荐的生命周期管理方式(更符合 ASGI 规范)。

二、核心使用方式

Starlette 的lifespan支持两种写法:装饰器写法(简单场景)和上下文管理器写法(复杂场景),下面分别演示。

前置准备

先安装依赖(确保 Starlette 版本 ≥ 0.25.0,推荐最新版):

pipinstallstarlette uvicorn
1. 装饰器写法(推荐新手)

适合启动/关闭逻辑简单、无需共享状态的场景,用@app.lifespan装饰异步函数,函数返回{"startup": 启动函数, "shutdown": 关闭函数}

fromstarlette.applicationsimportStarlettefromstarlette.responsesimportJSONResponseimportasyncio# 创建应用实例app=Starlette(debug=True)# ---------------------- 生命周期函数 ----------------------# 启动时执行asyncdefstartup_event():print("🚀 应用启动中...")# 模拟初始化数据库连接池awaitasyncio.sleep(1)# 模拟异步操作app.state.db="已初始化的数据库连接池"# 把资源存在app.state中,供视图使用print("✅ 应用启动完成(数据库连接已初始化)")# 关闭时执行asyncdefshutdown_event():print("🔌 应用关闭中...")# 模拟关闭数据库连接awaitasyncio.sleep(1)app.state.db=None# 释放资源print("❌ 应用关闭完成(数据库连接已释放)")# 注册生命周期钩子@app.lifespanasyncdeflifespan_manager(_):return{"startup":startup_event,"shutdown":shutdown_event}# ---------------------- 普通视图 ----------------------@app.route("/")asyncdefhomepage(request):# 从app.state获取生命周期中初始化的资源db_status="已连接"ifrequest.app.state.dbelse"未连接"returnJSONResponse({"message":"Hello Starlette","db_status":db_status})

运行命令:

uvicorn main:app --reload

运行效果

  • 启动时控制台输出:🚀 应用启动中...✅ 应用启动完成
  • 访问http://127.0.0.1:8000,返回{"message":"Hello Starlette","db_status":"已连接"}
  • 停止应用(按 Ctrl+C)时,控制台输出:🔌 应用关闭中...❌ 应用关闭完成
2. 上下文管理器写法(进阶)

适合需要更精细控制生命周期、或启动/关闭逻辑有依赖关系的场景(比如启动时创建的资源需要在关闭时显式清理),通过async with实现。

fromstarlette.applicationsimportStarlettefromstarlette.responsesimportJSONResponseimportasyncio app=Starlette(debug=True)# 上下文管理器风格的lifespan@app.lifespanasyncdeflifespan_manager(app):# ---------------------- 启动阶段(async with 进入时) ----------------------print("🚀 应用启动中(上下文管理器版)...")# 初始化资源app.state.redis="已初始化的Redis连接"awaitasyncio.sleep(1)print("✅ 启动完成(Redis已连接)")yield# 核心:yield 之前是启动逻辑,之后是关闭逻辑# ---------------------- 关闭阶段(async with 退出时) ----------------------print("🔌 应用关闭中(上下文管理器版)...")# 释放资源app.state.redis=Noneawaitasyncio.sleep(1)print("❌ 关闭完成(Redis已断开)")@app.route("/redis")asyncdefredis_status(request):redis_status="已连接"ifrequest.app.state.rediselse"未连接"returnJSONResponse({"message":"Redis状态","redis_status":redis_status})

核心特点

  • yield是分界点:代码执行到yield时,应用开始接收请求;
  • 应用关闭时,会执行yield之后的代码,确保资源被正确清理;
  • 这种写法更符合 Python 上下文管理器的习惯,也支持异常处理(比如在try/finally中包裹逻辑)。
3. 独立定义 lifespan(解耦写法)

如果生命周期逻辑复杂,可把lifespan抽成独立函数,再传给Starlette构造函数,代码更整洁:

fromstarlette.applicationsimportStarlettefromstarlette.responsesimportJSONResponse# 独立的lifespan函数asyncdefcustom_lifespan(app):# 启动逻辑app.state.config={"env":"dev","port":8000}yield# 关闭逻辑app.state.config=None# 创建应用时指定lifespanapp=Starlette(debug=True,lifespan=custom_lifespan,# 传入独立的lifespanroutes=[app.route("/config")(lambdarequest:JSONResponse(request.app.state.config))])

三、关键注意事项

  1. app.state的使用
    • 生命周期中初始化的资源(如数据库连接、配置),建议存在app.state中,视图函数可通过request.app.state访问;
    • app.state是全局的,多个请求共享,需注意异步安全(比如数据库连接池本身是异步安全的)。
  2. 必须是异步函数
    • lifespan及内部的启动/关闭函数都必须用async def定义,不能用同步函数;
    • 如果需要执行同步阻塞操作(比如加载本地大文件),建议用asyncio.to_thread包装,避免阻塞事件循环。
  3. 异常处理
    • 启动阶段如果抛出异常,应用会直接退出,不会接收请求;
    • 可在lifespan中加try/except捕获异常,比如:
      @app.lifespanasyncdeflifespan_manager(app):try:# 启动逻辑app.state.db=awaitinit_db()yieldexceptExceptionase:print(f"启动失败:{e}")raise# 重新抛出异常,让应用退出finally:# 关闭逻辑(无论是否异常都会执行)ifapp.state.db:awaitapp.state.db.close()

总结

  1. Starlette 的lifespan是管理应用启动/关闭生命周期的核心机制,替代了旧的on_startup/on_shutdown
  2. 常用两种写法:装饰器写法(简单场景)和上下文管理器写法(进阶/复杂场景),核心是通过app.state共享初始化的资源;
  3. lifespan函数必须是异步的,启动阶段异常会导致应用退出,关闭阶段建议通过finally确保资源释放。
http://www.jsqmd.com/news/133622/

相关文章:

  • 深度剖析北京顺义遗嘱咨询律所哪家好:2025-2026专业实力与客户反馈全解 - 老周说教育
  • Procyon终极指南:快速掌握Java反编译与元编程工具
  • OpenRGB终极指南:一站式掌控所有RGB设备的开源神器
  • Screenbox媒体播放器:打造Windows平台极致多媒体体验
  • 从Markdown到专业演示文稿:Marp CLI的创作革命
  • 如何从零掌握CS2游戏辅助开发:终极框架技术实战指南
  • AI搜索GEO优化公司如何选?AI排名优化服务商挑选指南和选购建议 - AIEO
  • TriPlayer源码架构解析:Switch后台音乐播放器的技术实现
  • 深入解析:【行测】判断推理秒杀技巧
  • 真空乳化机远程监控运维管理系统方案
  • 工业3D相机常见参数及分类的通用术语解读
  • 【国产大模型新突破】:Open-AutoGLM本地部署实测报告(性能提升300%的秘密)
  • 高效语音合成方案:GPT-SoVITS集成GPT+SoVITS双模型优势
  • 2025年合肥公寓出租/写字楼出租/办公室出租/园区推荐前十榜单:安徽广电文创产业园管理有限公司领衔 - 2025年品牌推荐榜
  • 2025-2026无锡短视频运营公司权威推荐,复购率TOP榜与精准获客方案指南 - 品牌鉴赏师
  • HarmonyOS开发之分布式硬件共享——使用虚拟设备
  • 【值得收藏】大模型微调技术:让你的AI模型适应特定任务的完整指南
  • 2025抗衰老的保健品十大品牌清单:抗衰老哪个产品好?真实用户反馈大汇总 - 博客万
  • 如何用BiliRaffle轻松搞定B站动态抽奖:2025最新完整教程
  • 如何充分利用Screenbox播放器?终极完整使用指南大揭秘
  • 2025年热门的金蝶Al可靠选择榜 - 品牌宣传支持者
  • 频域Transformer:突破图像去模糊技术瓶颈的智能解决方案
  • 2026年京东e卡回收哪里最划算?三大渠道深度解析 - 京顺回收
  • 什么是IPD咨询?解码企业高效研发的核心密码
  • 企业合同管理系统设计与实现springboot-计算机毕业设计源码+LW文档
  • 2025年12月优质家庭教育机构TOP5排名:科学赋能现代家庭教育 - 深度智识库
  • DeepAnaX发布全新「GEO优化分析统计系统」,以洞察力重塑AI营销决策
  • 2025年12月阿里巴巴全店托管代运营,阿里巴巴产品推广代运营,阿里巴巴爆款打造代运营公司推荐,询盘提升与GMV增长实测! - 品牌鉴赏师
  • 揭秘Open-AutoGLM离线版部署难题:5步实现零依赖本地推理(小白也能懂)
  • APatch深度解析:如何实现Android内核级系统定制与模块化开发