使用Uvicorn的--reload参数时能否排除特定代码?
解决方案:避免Uvicorn重载时重复加载耗时模型
当然可以实现!每次重载都重新加载大模型确实很烦人,这里有几个实用的方案,按复杂度从低到高排序:
方案1:用文件标记跳过重复加载
这个方法最简单,通过一个本地文件来标记模型是否已经加载完成,重载时检查文件存在就跳过加载步骤:
# main.py import os from fastapi import FastAPI MODEL_LOADED_FLAG = "./model_loaded.flag" model = None app = FastAPI() def load_model(): global model # 模拟耗时的模型加载 print("正在加载大型模型...(这一步只执行一次)") # 这里替换成你的实际模型加载代码 model = "加载完成的模型实例" # 创建标记文件 with open(MODEL_LOADED_FLAG, "w") as f: f.write("1") # 启动时检查标记 if not os.path.exists(MODEL_LOADED_FLAG): load_model() @app.get("/") async def root(): return {"message": "模型已就绪", "model_status": "已加载" if model else "未加载"} # 可选:添加一个接口手动触发模型重新加载 @app.post("/reload-model") async def reload_model(): global model if os.path.exists(MODEL_LOADED_FLAG): os.remove(MODEL_LOADED_FLAG) load_model() return {"message": "模型已重新加载"}
注意点:
- 如果你的模型有更新,需要手动删除
model_loaded.flag文件,或者调用/reload-model接口触发重新加载 - 标记文件最好放在项目目录外或者加入
.gitignore,避免提交到版本控制
方案2:将模型加载到独立进程,通过IPC调用
这个方案更可靠,把模型放在单独的进程中运行,Uvicorn重载时只重启API服务进程,模型进程保持运行:
步骤1:编写模型服务脚本(model_service.py)
# model_service.py from multiprocessing import Process, Pipe def model_process(conn): # 这里加载你的耗时模型 print("启动模型进程,加载大型模型...") model = "加载完成的模型实例" while True: # 等待API进程的请求 request = conn.recv() if request == "predict": # 模拟模型预测逻辑 result = "模型预测结果" conn.send(result) elif request == "shutdown": break if __name__ == "__main__": pass
步骤2:在主API脚本中调用模型进程
# main.py from fastapi import FastAPI from multiprocessing import Pipe, Process import model_service app = FastAPI() # 启动模型进程 parent_conn, child_conn = Pipe() model_proc = Process(target=model_service.model_process, args=(child_conn,)) model_proc.start() @app.get("/predict") async def predict(): parent_conn.send("predict") result = parent_conn.recv() return {"prediction": result} # 关闭应用时终止模型进程 @app.on_event("shutdown") def shutdown_event(): parent_conn.send("shutdown") model_proc.join()
优势:
- Uvicorn重载时,模型进程不会重启,完全避免重复加载
- API和模型解耦,后续可以单独扩展模型服务
方案3:使用磁盘缓存加速模型加载
如果不想搞多进程,可以用diskcache之类的库把加载好的模型序列化到磁盘,下次加载直接从缓存读取,速度会快很多:
# main.py from fastapi import FastAPI from diskcache import Cache app = FastAPI() cache = Cache("./model_cache") @cache.memoize(expire=None) # 永久缓存 def load_model(): print("正在加载大型模型...(首次加载后会缓存)") # 替换成你的模型加载代码 return "加载完成的模型实例" model = load_model() @app.get("/") async def root(): return {"message": "模型已就绪"}
注意点:
- 安装依赖:
pip install diskcache - 如果模型更新了,需要清空缓存目录
./model_cache
为什么直接排除代码行不可行?
Uvicorn的--reload机制是通过监控文件变化,重启整个Python进程并重新加载所有模块代码。它没有提供“跳过特定代码行”的功能,因为重载本质是重新执行整个应用的启动逻辑。所以我们需要通过上面的缓存、进程分离等方式来绕过重复加载。
内容的提问来源于stack exchange,提问作者utengr
相关产品推荐
相关产品推荐

