You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 03:18:06