首页 > 解决方案 > Matplotlib 实时图能够处理数据更新之间的长时间

问题描述

我注意到,每一种以不断增加的长度绘制连续更新数据(我发现)的解决方案都有一个巨大的挫折——如果数据没有立即出现,matplotlib 窗口就会冻结(说没有响应)。以此为例:

from matplotlib import pyplot as plt
from matplotlib import animation
from random import randint
from time import sleep
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
line, = ax.plot([])
x = []
y = []
def animate(i):
    x.append(i)
    y.append(randint(0,10))
    for i in range(100000000):
        # Do calculations to attain next data point
        pass
    line.set_data(x, y)
    return line,

anim = animation.FuncAnimation(fig, animate,
                               frames=200, interval=20, blit=True)
plt.show()

此代码在动画函数中没有数据采集循环的情况下工作正常,但有了它,图形窗口就会冻结。也拿这个:

plt.ion()
x = []

for i in range(1000):
    x.append(randint(0,10))
    for i in range(100000000):
        # Do calculations to attain next data point
        pass
    plt.plot(x)
    plt.pause(0.001)

也会结冰。(感谢上帝,因为使用这种方法几乎不可能关闭,因为图表一直在所有内容前面弹出。我不建议取消睡眠)

这个也是:

plt.ion()
x = []

for i in range(1000):
    x.append(randint(0,10))
    for i in range(100000000):
        # Do calculations to attain next data point
        pass
    plt.plot(x)
    plt.draw()
    plt.pause(0.001)
    plt.clf()

还有这个:(从https://stackoverflow.com/a/4098938/9546874复制)

import matplotlib.pyplot as plt
import numpy as np
from time import sleep
x = np.linspace(0, 6*np.pi, 100)
y = np.sin(x)

# You probably won't need this if you're embedding things in a tkinter plot...
plt.ion()

fig = plt.figure()
ax = fig.add_subplot(111)
line1, = ax.plot(x, y, 'r-') # Returns a tuple of line objects, thus the comma

for phase in np.linspace(0, 10*np.pi, 500):
    line1.set_ydata(np.sin(x + phase))
    for i in range(100000000):
        # Do calculations to attain next data point
        pass
    fig.canvas.draw()
    fig.canvas.flush_events()

这是一个巨大的问题,因为认为所有数据都会以一致的时间间隔出现是天真的。我只想要一个在数据到来时更新的图表,并且不会在停机时间内崩溃。请记住,数据之间的间隔可能会发生变化,可能是 2 秒或 5 分钟。

编辑:

经过进一步测试,FuncAnimation可以使用,但是它非常hacky,并且仍然有点损坏。如果将 增加到interval的预期时间以上animate,它会起作用,但每次平移或缩放图形时,所有数据都会消失,直到下一次更新。因此,一旦您有了视图,就无法触摸它。

编辑:

为了清楚起见,将 sleep 更改为 for 循环

标签: pythonmatplotlib

解决方案


更新答案:问题是数据采集或生成和 matplotlib 窗口在同一个线程上运行,因此前者阻塞了后者。为了克服这个问题,将数据采集移动到一个单独的过程中,如本例所示。除了进程和管道,您还可以使用线程和队列。


推荐阅读