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

使用Matplotlib绘制实时数据时遇PyEval_RestoreThread错误求助

问题

尝试用Python的Matplotlib绘制实时更新数据时出现报错,代码如下:

plt.rcParams['animation.html'] = 'jshtml'
fig = plt.figure()
ax = fig.add_subplot(111)
fig.show()

i = 0
plot_x , plot_y = [], []

while True :

    ###some code to get live updating x_in_data###

    x_in_data = np.reshape(x_in, (1))

    print(x_in_data)


    plot_x.append(i)
    plot_y.append(x_in_data[0])
    ax.plot(plot_x, plot_y, color='b')
    fig.canvas.draw()

    ax.set_xlim(left=max(0, i-50), right= i+50)

    time.sleep(0.1)
    i += 1

报错信息:

Fatal Python error: PyEval_RestoreThread: NULL tstate
Python runtime state: initialized
Current thread 0x00004fc4 (most recent call first):

程序弹出绘图窗口但无法正常工作,试过网上方案无效。数据是逐行更新的,格式示例:

[-18.75235738]
[-19.02642986]
[-18.75235738]
[-19.02642986]
[-18.75235738]
[-19.02642986]
[-18.92591474]
[-18.75235738]

想知道该错误是否和数据更新方式有关,同时求高效绘制这类逐行更新数据的方法。

解决方案

错误原因

这个报错和数据更新方式无关,是因为你用while True循环加time.sleep阻塞了Matplotlib的事件循环,导致绘图线程和主线程冲突,触发了线程状态恢复的致命错误。

高效实现方法

方法1:使用FuncAnimation(推荐)

Matplotlib的FuncAnimation会自动处理事件循环,避免线程冲突,性能更优:

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np

# 初始化绘图
fig, ax = plt.subplots()
line, = ax.plot([], [], color='b')
ax.set_xlim(0, 50)
ax.set_ylim(-20, -18)  # 根据你的数据范围调整

plot_x, plot_y = [], []
i = 0

def update(frame):
    global i, plot_x, plot_y
    # 替换成你的实际数据获取逻辑
    x_in = np.random.uniform(-19.1, -18.7)
    x_in_data = np.reshape(x_in, (1))
    
    plot_x.append(i)
    plot_y.append(x_in_data[0])
    
    # 只保留最近50个数据点,优化性能
    if len(plot_x) > 50:
        plot_x = plot_x[-50:]
        plot_y = plot_y[-50:]
    
    line.set_data(plot_x, plot_y)
    ax.set_xlim(max(0, i-50), i+10)
    i += 1
    return line,

# interval是更新间隔(毫秒),blit=True提升绘图效率
ani = FuncAnimation(fig, update, interval=100, blit=True)
plt.show()

方法2:修复原循环的事件处理

如果坚持用while True循环,需要在每次绘图后处理事件队列:

import matplotlib.pyplot as plt
import numpy as np
import time

plt.rcParams['animation.html'] = 'jshtml'
fig = plt.figure()
ax = fig.add_subplot(111)
line, = ax.plot([], [], color='b')  # 只创建一条线,重复更新数据
ax.set_xlim(0, 50)
ax.set_ylim(-20, -18)

i = 0
plot_x , plot_y = [], []

while True :
    # 替换成你的实际数据获取逻辑
    x_in = np.random.uniform(-19.1, -18.7)
    x_in_data = np.reshape(x_in, (1))

    plot_x.append(i)
    plot_y.append(x_in_data[0])
    
    # 限制数据点数量
    if len(plot_x) > 50:
        plot_x = plot_x[-50:]
        plot_y = plot_y[-50:]
    
    line.set_data(plot_x, plot_y)
    ax.set_xlim(left=max(0, i-50), right= i+10)
    
    fig.canvas.draw()
    fig.canvas.flush_events()  # 关键:处理事件队列,避免阻塞
    time.sleep(0.1)
    i += 1

关键优化点

  • 不要每次循环调用ax.plot(),这会不断创建新线条,导致内存飙升,应该创建单条线后用set_data()更新数据。
  • 限制保留的数据点数量,避免数据量过大影响性能。
  • 通过FuncAnimation或flush_events()处理Matplotlib事件循环,避免线程冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 18:57:09