FastAPI中跨APIRouter优雅访问config.yaml的方案(解决导入报错)
FastAPI跨模块访问配置的优雅解决方案
你遇到的ImportError: attempted relative import beyond top-level package错误,本质是因为直接运行main.py时,它被当作顶层脚本而非project_root包的一部分,相对导入无法跳出当前模块的层级范围。下面是几种更优雅的解决方式:
方案1:抽离独立配置模块(最推荐)
把配置加载逻辑单独封装成独立模块,彻底解耦配置与业务代码,所有模块都能直接导入使用。
- 在
config/目录下新建config.py,写入配置加载逻辑:
import yaml def load_config(): # 从项目根目录运行脚本时,该路径有效 with open("config/config.yaml", "r", encoding="utf-8") as f: return yaml.safe_load(f) # 提前加载配置,供其他模块直接导入 config = load_config()
- 修改
main.py,从独立配置模块导入:
import uvicorn from fastapi import FastAPI from api import api_router from config.config import config # 导入独立模块的配置 app = FastAPI() app.include_router(api_router) if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000)
- 修改
api/endpoint1.py,直接导入配置:
from fastapi import APIRouter from config.config import config router = APIRouter() @router.get("/path/") def func(): return {"some_config": config["some_key"]}
优点:配置逻辑独立,代码结构清晰,所有模块可直接访问,符合模块化设计原则。
方案2:利用FastAPI的app.state存储配置
FastAPI的app.state允许你在应用实例上存储全局状态,路由可通过请求对象获取配置。
- 修改
main.py,将配置存入app.state:
import uvicorn import yaml from fastapi import FastAPI from api import api_router def load_config(): with open("config/config.yaml", "r", encoding="utf-8") as f: return yaml.safe_load(f) config = load_config() app = FastAPI() app.state.config = config # 将配置绑定到应用状态 app.include_router(api_router) if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000)
- 修改
api/endpoint1.py,通过Request对象获取配置:
from fastapi import APIRouter, Request router = APIRouter() @router.get("/path/") def func(request: Request): config = request.app.state.config return {"some_config": config["some_key"]}
优点:无需新增模块,利用FastAPI原生机制;缺点:每个需要配置的路由都要注入Request对象。
方案3:使用FastAPI依赖注入(DI)
通过依赖注入统一提供配置,适合需要对配置做动态处理的场景,后续修改配置获取逻辑时只需调整依赖函数。
- 新建
api/dependencies.py(或直接在配置模块中定义):
from config.config import config # 复用方案1的独立配置模块 def get_config(): return config
- 修改
api/endpoint1.py,通过Depends注入配置:
from fastapi import APIRouter, Depends from api.dependencies import get_config router = APIRouter() @router.get("/path/") def func(config=Depends(get_config)): return {"some_config": config["some_key"]}
优点:高度灵活,可在依赖函数中添加配置校验、动态加载等逻辑,所有路由自动生效;符合FastAPI的设计理念。
内容的提问来源于stack exchange,提问作者Python coder
相关产品推荐
相关产品推荐

