Flask应用中全局变量值在子线程中未更新问题求助
问题根因及修复方案
核心问题点
- 线程入口函数
bg_func被错误绑定为@app.route("/")的视图函数,路由函数是Flask用于响应HTTP请求的逻辑,不能作为子线程的入口使用,逻辑完全错位。 - 若你开启了Flask Debug模式(
app.run(debug=True)),Flask默认会启动两个独立进程:一个负责监听代码变更自动重载,一个处理业务请求。你创建的子线程运行在重载进程中,路由修改的web变量属于工作进程的内存副本,两个进程的全局变量完全隔离,自然修改不会同步到子线程。 - 普通全局布尔变量在多线程场景下可能存在CPU缓存一致性问题,导致子线程读取到的是旧值。
修复方案
1. 替换全局标志位为threading.Event
用Python标准库threading.Event做线程启停控制,原生线程安全,不会有缓存读取问题:
import threading # 初始化事件标志,默认True对应子线程运行,False对应子线程暂停 pause_event = threading.Event() pause_event.set() # set()状态下wait()直接放行,clear()状态下wait()阻塞
2. 修正线程入口函数,解绑路由
# 不要给线程入口加路由装饰器 def bg_func(): print('Thread test') while True: # 标志为False时阻塞等待,对应原web=True时的暂停逻辑 pause_event.wait() if Facial_Check.run() == True: face_detected = True # 启动线程,加daemon=True保证主进程退出时子线程自动销毁 t = threading.Thread(target=bg_func, daemon=True) t.start() # 原/路由如果需要返回页面单独定义 @app.route("/") def index(): return render_template('index.html')
3. 调整路由控制逻辑
@app.route("/<changePin>/<action>") def action(changePin, action): changePin = int(changePin) deviceName = pins[changePin]['name'] current_status = False if action == "on": GPIO.output(changePin, GPIO.HIGH) time.sleep(1) GPIO.output(changePin, GPIO.LOW) # 对应原web=True,暂停子线程 pause_event.clear() current_status = True message = "Turned computer on." if action == "off": GPIO.output(changePin, GPIO.HIGH) time.sleep(1) GPIO.output(changePin, GPIO.LOW) # 对应原web=False,恢复子线程运行 pause_event.set() current_status = False face_detected = False message = "Turned computer off." for pin in pins: pins[pin]['state'] = GPIO.input(pin) return render_template('index.html', Status=current_status)
4. 调整Flask启动参数
如果要保留Debug模式,启动时关闭自动重载避免双进程:
if __name__ == '__main__': app.run(debug=True, use_reloader=False)
生产环境直接关闭Debug模式即可。
内容的提问来源于stack exchange,提问作者Comyar D
相关产品推荐
相关产品推荐

