跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

如何使用 Matplotlib 实现真空压力数据的实时动态更新绘图

本文详解如何避免 matplotlib 每次循环都弹出新窗口,通过正确复用 figure 和 axes 对象,实现单窗口内连续更新压力曲线,适用于 tcp 通信采集的实时传感器 数据可视化 。 在使用 Matplotlib 进行实时数据可视化时,一个常见误区是: 在循环内部反复调用 plt.figure() 或 pyplot.figure() —— 这会为每一次迭代创建全新的图形窗口,导致“每读一个值就弹出一个新图”的问题。您提供的代码中,figure = pyplot.figure() 被错误地放在了 while 循环内部,这是根本原因。 要实现真正的“动态更新”(即同一窗口持续刷新曲线),必须将图形对象(figure 和 axes)的创建 移至循环外部 ,仅在循环中更新数据并 重绘 。以下是优化后的核心结构与完整可运行示例: CentOS Stream 9 CentOS Stream 9是基于RHEL 9技术路线的持续交付版本,适合需要贴近RHEL 9生态的软件开发、系统集成和测试环境。它相比传统CentOS Linux更靠近上游开发过程,用户可以更早看到RHEL 9后续小版本中的软件包变化。CentOS Stream 9仍是当前可用的官方版本线之一,适合对稳定性和新功能之间有平衡需求的团队使用。 下载 ✅ 正确做法:分离初始化与更新逻辑
import socket import time import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation from datetime import datetime # --- 1. 初始化 TCP 连接 --- target_host = "10.1.2.121" target_port = 50 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((target_host, target_port)) print(f"Connected to {target_host}:{target_port}") # --- 2. 初始化绘图(⚠️ 关键:只执行一次!)--- plt.yscale('symlog') plt.grid(True) fig, ax = plt.subplots(figsize=(10, 6)) line, = ax.plot([], [], 'b-', linewidth=2, label='Vacuum Pressure (Torr)') ax.set_xlabel('Time') ax.set_ylabel('Pressure (Torr)') ax.legend() ax.ticklabel_format(axis='y', style='sci', scilimits=(0,0)) # 数据缓冲区(限制历史长度,防止内存溢出) max_points = 200 x_data, y_data = [], [] # --- 3. 定义动画更新函数 --- def update_frame(frame): try: # 发送命令 & 解析响应 client.send(b'?VP\r\0') response = client.recv(1024).decode('ascii').strip() # 示例响应: "VP:3.58E-7" → 提取数值 if response.startswith("VP:"): val_str = response[3:].replace("E", "e") pressure = float(val_str) # 更新数据 now = datetime.now() x_data.append(now) y_data.append(pressure) # 限制数据点数量(可选) if len(x_data) > max_points: x_data.pop(0) y_data.pop(0) # 刷新线条数据 line.set_data(x_data, y_data) # 自动调整坐标轴范围 ax.relim() ax.autoscale_view() print(f"[{now.strftime('%H:%M:%S')}] Pressure: {pressure:.2e} Torr") except Exception as e: print(f"Read error: {e}") return line, # --- 4. 启动动画(非阻塞,支持后台持续采集)--- ani = FuncAnimation(fig, update_frame, interval=200, blit=False, cache_frame_data=False) # 显示图形(保持主线程运行) plt.show() # ⚠️ 注意:plt.show() 后的代码不会执行;如需优雅退出,建议用信号或 GUI 事件控制
? 关键要点总结 禁止在循环中新建 figure/axis :plt.figure()、plt.subplot()、fig, ax = plt.subplots() 等必须置于循环外。 使用 FuncAnimation 替代手动循环绘图 :它内置帧调度、重绘优化与事件循环管理,比 plt.ion() + plt.pause() 更稳定可靠。 显式调用 ax.relim() 和 ax.autoscale_view() :确保每次新增数据后坐标轴自动适配范围。 添加异常处理与日志输出 :TCP 通信易受网络波动影响,避免因单次失败中断整个动画。 考虑数据缓存策略 :长时间运行时,限制 x_data/y_data 长度,防止内存泄漏。 ? 提示:若后续集成 GUI(如 PyQt/PySide),应改用 FigureCanvasQTAgg 嵌入控件,并通过 QTimer 触发更新,而非 FuncAnimation——后者依赖 plt.show() 的主事件循环,在 GUI 中可能冲突。 遵循以上结构,您即可获得一个稳定、低延迟、单窗口持续更新的真空压力实时曲线图,为后续构建完整监控系统打下坚实基础。

相关文章