如何在uvicorn启动时执行自定义脚本并缓存数据供FastAPI服务使用
实现方案
方案1:使用FastAPI内置的生命周期事件(推荐)
FastAPI本身提供了应用启动前的触发钩子,会在uvicorn加载应用完成、开始对外接收请求之前自动执行,完全匹配预加载缓存的需求。
0.93及以上版本的FastAPI推荐使用lifespan上下文管理器实现:
from fastapi import FastAPI from contextlib import asynccontextmanager # 可以是全局内存缓存、Redis连接对象等你用到的缓存载体 cache = {} @asynccontextmanager async def lifespan(app: FastAPI): # 启动前逻辑:写你的数据库拉取、缓存生成代码 # 示例:拉取配置表写入缓存 # config_data = db_session.query(Config).all() # for item in config_data: # cache[item.config_key] = item.config_value print("缓存预加载完成") yield # 应用停止时的逻辑(不需要可以不写),比如清理资源、关闭数据库连接 app = FastAPI(lifespan=lifespan) # 业务接口直接复用缓存即可 @app.get("/get_config") def get_config(config_key: str): return cache.get(config_key)
低版本FastAPI可以用startup事件装饰器实现:
from fastapi import FastAPI app = FastAPI() cache = {} @app.on_event("startup") def preload_cache(): # 你的缓存预加载逻辑写这里 print("缓存预加载完成")
该方案的优势是逻辑和应用绑定,不管用命令行还是代码方式启动uvicorn都会触发,不需要调整启动参数,适配绝大多数场景。
方案2:在uvicorn启动代码中前置执行逻辑
如果你是用Python代码直接启动uvicorn,而非uvicorn命令行启动,可以在调用uvicorn运行前先执行你的预加载逻辑:
import uvicorn from your_app_file import app def preload_cache(): # 你的缓存预加载逻辑 print("缓存预加载完成") if __name__ == "__main__": # 先执行预加载,再启动服务 preload_cache() uvicorn.run(app, host="0.0.0.0", port=8000)
该方案适合多worker部署、且缓存为全局共享(比如Redis、共享内存)的场景,预加载逻辑只会在主进程执行一次,不会每个worker重复运行。如果你的缓存是worker本地内存存储,还是选择方案1更合适,会自动在每个worker启动时各执行一次预加载。
注意事项
- 多worker部署时先明确你的需求:全局只预加载一次选方案2,每个worker都要生成本地缓存选方案1
- 预加载逻辑耗时较长时建议加进度日志,避免误判为启动卡住
- 预加载失败时建议直接抛出异常终止启动,避免服务运行后缓存不可用导致业务异常
内容的提问来源于stack exchange,提问作者user1591156
相关产品推荐
相关产品推荐

