FastAPI无法读取后台线程修改的全局变量问题求助
问题原因与解决方案
根本原因
你遇到的问题核心是**reload=True导致的进程隔离**。当开启reload模式时,Uvicorn会启动两个进程:一个监控文件变化的主进程,以及一个实际处理请求的子进程。你在if __name__ == '__main__'里启动的后台线程属于主进程,修改的是主进程的globalVar;而处理API请求的子进程会重新加载整个模块,子进程内的globalVar保持初始值0,因此断言失败。
解决方案
方案1:关闭热重载(生产/调试无热重载需求时)
直接将reload=True改为reload=False,此时Uvicorn仅启动一个进程,后台线程与API接口共享同一全局变量空间:
from fastapi import FastAPI from threading import Thread from time import sleep app = FastAPI() globalVar = 0 @app.get("/") def read_root(): global globalVar assert globalVar > 0 return {"Hello": globalVar} def task(): global globalVar sleep(2) # 确保服务启动完成后再修改变量 globalVar = 1 print('globalVar set') if __name__ == '__main__': Thread(target=task, args=()).start() import uvicorn uvicorn.run('fasterror:app', host='127.0.0.1', port=8000, reload=False, access_log=True, workers=1)
方案2:保留热重载(开发环境需要实时更新代码时)
将后台线程的启动逻辑移到模块级别(而非if __name__ == '__main__'内),这样Uvicorn重启子进程时,会重新执行模块代码并在子进程内启动线程,修改子进程的全局变量:
from fastapi import FastAPI from threading import Thread from time import sleep import threading app = FastAPI() globalVar = 0 _thread_started = False lock = threading.Lock() # 可选:保证线程安全 @app.get("/") def read_root(): global globalVar with lock: assert globalVar > 0 return {"Hello": globalVar} def task(): global globalVar sleep(2) with lock: globalVar = 1 print('globalVar set') # 模块导入时启动线程,避免重复启动 if not _thread_started: Thread(target=task, args=()).start() _thread_started = True if __name__ == '__main__': import uvicorn uvicorn.run('fasterror:app', host='127.0.0.1', port=8000, reload=True, access_log=True, workers=1)
额外说明
- 即使在单线程/单进程环境下,复杂的全局变量操作(如增量、多属性修改)建议使用
threading.Lock保证线程安全,避免竞态条件。 - 若需要跨进程共享变量(比如开启多个workers),全局变量不再适用,需改用外部存储(如Redis、数据库)或进程间通信机制(如
multiprocessing.Queue)。
内容的提问来源于stack exchange,提问作者Eva4684
相关产品推荐
相关产品推荐

