如何在FastAPI + Uvicorn运行时注入硬件状态对象的引用?
如何在FastAPI + Uvicorn运行时注入硬件状态对象的引用?
我明白你的痛点——想把提前初始化好的硬件状态对象传给FastAPI,又不想把初始化逻辑和API代码混在一起,确实刚开始容易卡壳。下面给你几个实用的方案,都是FastAPI生态里常用的做法:
方案一:用FastAPI原生依赖注入(推荐)
这种方式最符合FastAPI的设计理念,而且方便后续测试(比如替换成模拟对象),耦合度也低。
首先把硬件初始化逻辑单独放在一个文件里,比如hardware_setup.py:
# hardware_setup.py class Terminal: def __init__(self, runtime_config): self.config = runtime_config # 这里写硬件初始化的逻辑,比如连接设备、加载配置等 def status(self): # 返回硬件状态的具体逻辑 return {"hardware_state": "active", "config": self.config} # 根据用户输入和运行时配置创建实例的函数 def create_terminal_instance(): # 这里模拟获取运行时配置,比如从环境变量、命令行参数读取 runtime_config = {"baud_rate": 9600, "device_port": "/dev/ttyUSB0"} return Terminal(runtime_config)
然后在myapp.py里通过依赖注入拿到这个实例:
# myapp.py import uvicorn from fastapi import FastAPI, Depends from hardware_setup import create_terminal_instance, Terminal # 提前初始化好Terminal实例 terminal = create_terminal_instance() fastapi = FastAPI() # 定义一个依赖函数,返回我们的硬件实例 def get_terminal() -> Terminal: return terminal @fastapi.get("/status") async def get_hardware_status(terminal: Terminal = Depends(get_terminal)): # 直接使用注入的实例 return terminal.status() if __name__ == '__main__': uvicorn.run("myapp:fastapi", host="0.0.0.0", port=10101)
方案二:把实例挂载到FastAPI应用的state属性上
这种方式更直接,适合简单场景,不需要额外的依赖函数:
修改myapp.py如下:
# myapp.py import uvicorn from fastapi import FastAPI from hardware_setup import create_terminal_instance fastapi = FastAPI() # 在应用创建后,把硬件实例挂载到app.state上(这是FastAPI专门用来存应用级状态的地方) fastapi.state.terminal = create_terminal_instance() @fastapi.get("/status") async def get_hardware_status(): # 直接通过app.state访问实例 return fastapi.state.terminal.status() if __name__ == '__main__': uvicorn.run("myapp:fastapi", host="0.0.0.0", port=10101)
方案三:全局变量(不推荐,适合小型项目)
如果你的项目非常简单,也可以用全局变量,但这种方式耦合度高,测试时不好替换实例,不推荐大型项目使用:
在hardware_setup.py里直接创建全局实例:
# hardware_setup.py # ... 之前的Terminal类和create_terminal_instance函数 ... # 直接创建全局实例 terminal_instance = create_terminal_instance()
然后在myapp.py里直接导入使用:
# myapp.py from hardware_setup import terminal_instance @fastapi.get("/status") async def get_hardware_status(): return terminal_instance.status()
额外提示:异步初始化的情况
如果你的硬件初始化是异步操作(比如需要异步连接设备),可以用FastAPI的lifespan事件来处理:
# myapp.py async def lifespan(app: FastAPI): # 应用启动前异步初始化硬件 app.state.terminal = await create_terminal_async() yield # 应用关闭时异步清理资源 await app.state.terminal.disconnect() fastapi = FastAPI(lifespan=lifespan)
总结一下,优先选方案一或方案二,这两种都是FastAPI官方推荐的做法,既优雅又便于维护。
备注:内容来源于stack exchange,提问作者Henry
相关产品推荐
相关产品推荐

