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

使用PyQtGraph实时绘制多传感器外部数据的问题求助

解决PyQtGraph多进程绘图无法更新的问题

看起来你遇到了多进程环境下PyQtGraph绘图更新的典型问题,核心原因是跨进程内存隔离和代码逻辑的小失误,下面一步步帮你解决:

问题根源分析

  1. 全局变量跨进程无效:多进程拥有独立的内存空间,你通过globals()['DatExt1']试图获取主进程的队列是行不通的——子进程的全局命名空间和主进程完全隔离,DatExt1只是ShowData函数的局部变量,根本不在子进程的全局变量里。
  2. 代码笔误:update2方法中更新910D绘图时,错误使用了self.data1的数据,应该用self.data2。
  3. 队列读取方式可能阻塞事件循环:直接用empty()判断后get(),虽然不会死等,但不如用非阻塞读取更稳妥,避免影响Qt事件循环的响应。

修正后的完整代码

绘图模块(比如命名为PlotData.py)

from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import pyqtgraph as pg
import sys
import multiprocessing

class Plot2D():
    def __init__(self, queue_mpu, queue_910d):
        self.traces = dict()
        self.app = QtGui.QApplication([])
        self.win = pg.GraphicsWindow(title="传感器数据绘图")
        self.win.resize(1000, 600)
        self.win.setWindowTitle('实时数据监控')
        pg.setConfigOptions(antialias=True)
        
        # 创建两个绘图区域
        self.waveform_mpu = self.win.addPlot(title='MPU 数据', row=1, col=1)
        self.waveform_910d = self.win.addPlot(title='910D 数据', row=2, col=1)
        
        # 保存传入的队列(关键:直接关联到实例,不用全局变量)
        self.queue_mpu = queue_mpu
        self.queue_910d = queue_910d

    def start(self):
        # 直接用当前实例的QApplication执行事件循环,比instance()更可靠
        if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
            self.app.exec_()

    def set_plotdata(self, name, data_x, data_y):
        if name in self.traces:
            self.traces[name].setData(data_x, data_y)
        else:
            # 首次创建绘图轨迹
            if name == '910D':
                self.traces[name] = self.waveform_910d.plot(pen='c', width=3)
            if name == 'MPU':
                self.traces[name] = self.waveform_mpu.plot(pen='c', width=3)

    def update_plot(self):
        # 非阻塞读取MPU队列数据,避免阻塞Qt事件循环
        while not self.queue_mpu.empty():
            try:
                data = self.queue_mpu.get_nowait()
                self.set_plotdata('MPU', data[0], data[1])
            except multiprocessing.queues.Empty:
                break
                
        # 读取910D队列数据(修正了之前的笔误)
        while not self.queue_910d.empty():
            try:
                data = self.queue_910d.get_nowait()
                self.set_plotdata('910D', data[0], data[1])
            except multiprocessing.queues.Empty:
                break

    def start_animation(self):
        timer = QtCore.QTimer()
        timer.timeout.connect(self.update_plot)
        timer.start(60)  # 每60ms更新一次绘图
        self.start()

def ShowData(Data1, Data2):
    # 直接把队列传给Plot2D实例,不用依赖全局变量
    plotter = Plot2D(Data1, Data2)
    plotter.start_animation()

主进程代码(main.py)

import multiprocessing as mp
import numpy as np
import time
import PlotData

if __name__ == '__main__':
    # 创建两个进程间通信队列
    queue_mpu = mp.Queue()
    queue_910d = mp.Queue()
    
    # 启动绘图子进程
    plotting_process = mp.Process(target=PlotData.ShowData, args=(queue_mpu, queue_910d,))
    plotting_process.start()
    
    # 模拟传感器数据生成
    t = np.arange(-3.0, 2.0, 0.01)
    i = 0.0
    try:
        while True:
            # 生成MPU模拟数据
            mpu_data = np.sin(2 * 2 * np.pi * t) / (2 * np.pi * t + i)
            queue_mpu.put([t, mpu_data])
            
            # 生成910D模拟数据(测试用)
            sensor_910d_data = np.cos(2 * np.pi * t + i)
            queue_910d.put([t, sensor_910d_data])
            
            time.sleep(1)
            i += 0.1
    except KeyboardInterrupt:
        # 捕获Ctrl+C,优雅终止绘图进程
        plotting_process.terminate()
        plotting_process.join()

关键修改说明

  1. 队列直接传入绘图实例:不再依赖全局变量,把队列作为参数传递给Plot2D的构造函数,确保子进程能直接访问到通信队列。
  2. 非阻塞队列读取:用get_nowait()配合异常捕获,避免队列空时阻塞Qt的事件循环,保证GUI始终响应流畅。
  3. 修正数据更新笔误:更新910D绘图时使用正确的队列数据,不再复用MPU的数据。
  4. 优雅终止进程:主进程捕获KeyboardInterrupt信号,主动终止绘图子进程,避免产生僵尸进程。

额外注意事项

  • Qt的GUI控件只能由创建它的进程操作,所有绘图更新逻辑必须在子进程内完成(这已经在代码中实现)。
  • 如果传感器数据量很大,可以给队列设置maxsize参数(比如mp.Queue(maxsize=10)),避免内存占用过高。
  • 确保PyQtGraph和PyQt/PySide版本兼容,建议使用较新的稳定版本。

内容的提问来源于stack exchange,提问作者arlen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:25:48