Flask-SocketIO中GPU监控服务无法广播数据且请求上下文报错的问题求助
Flask-SocketIO中GPU监控服务无法广播数据且请求上下文报错的问题求助
我现在遇到了一个Flask-SocketIO的问题:我的服务器已经正常运行,Socket连接也没问题,我想做一个GPU监控服务,把GPU使用数据广播给所有连接的客户端,但目前监控服务里的广播没有生效,还出现了Working outside of request context的错误。
我的主服务代码如下:
from flask import Flask, request, jsonify, send_file from flask_socketio import SocketIO from services.GPU_Monit import GPUMonitorService socketio = SocketIO(...) gpu_service = GPUMonitorService(socketio) @socketio.on("connect") def handle_connect(): client_id = request.sid # Get the unique socket ID of the client print(f"Client connected: {client_id}") # Emit the new client's ID to all connected clients socketio.emit( # <---this is working "new_connection", {"socket_id": client_id}, )
我的GPU监控服务代码(GPU_Monit.py):
from flask_socketio import emit class GPUMonitorService: def __init__(self, socketio): self.socketio = socketio self.thread = threading.Thread(target=self._monitoring_task, daemon=True) self.thread.start() def _monitoring_task(self): while True: try: gpu_info = self.get_detailed_gpu_info() if gpu_info: #This line does run, but the connected sockets are not getting any messages emit("gpu_update", gpu_info, broadcast=True) except Exception as e: print(f"Error in GPU monitoring: {e}") time.sleep(10)
问题根源分析
出现这个问题有两个核心原因:
- 请求上下文缺失:直接调用的
emit函数默认依赖当前的请求/连接上下文,但监控任务是在独立后台线程中运行的,这里没有活跃的HTTP请求或Socket连接上下文,所以会抛出Working outside of request context错误。 - 广播方式错误:后台线程中不能用这种绑定到当前连接的
emit,而应该使用传入的全局socketio实例来调用emit,它可以在任意线程中触发广播,无需依赖上下文。
修复后的GPU监控服务代码
把GPU_Monit.py修改成这样(补上缺失的导入,修正缩进,替换广播方式):
import threading import time class GPUMonitorService: def __init__(self, socketio): self.socketio = socketio self.thread = threading.Thread(target=self._monitoring_task, daemon=True) self.thread.start() def get_detailed_gpu_info(self): # 保持你原本的GPU信息获取逻辑不变 return {} # 示例返回,实际替换为你的逻辑 def _monitoring_task(self): while True: try: gpu_info = self.get_detailed_gpu_info() if gpu_info: # 改用socketio实例的emit进行广播 self.socketio.emit( "gpu_update", gpu_info, broadcast=True ) except Exception as e: print(f"Error in GPU monitoring: {e}") time.sleep(10)
修复逻辑说明
self.socketio.emit是全局SocketIO对象的广播方法,它不依赖任何请求或连接上下文,能在后台线程、定时任务等任意环境中安全使用,直接把消息推送给所有连接的客户端。而原来的emit是绑定到当前连接上下文的版本,只能在handle_connect这类有活跃连接的事件处理器中使用。
另外注意修正了原代码中类方法缩进错误的问题,Python类的成员方法必须正确缩进才能被识别。
备注:内容来源于stack exchange,提问作者Barrard
相关产品推荐
相关产品推荐

