我有问题,试图使matplotlib绘图函数没有阻塞执行。

我已经尝试使用show(block=False)作为一些人的建议,但我得到的只是一个冻结的窗口。如果我简单地调用show(),结果会被正确地绘制,但执行会被阻塞,直到窗口关闭。从我读过的其他线程来看,我怀疑show(block=False)是否有效取决于后端。这对吗?我的后台是Qt4Agg。你能不能看一下我的代码,如果有什么问题请告诉我?这是我的代码。

from math import *
from matplotlib import pyplot as plt
print(plt.get_backend())


def main():
    x = range(-50, 51, 1)
    for pow in range(1,5):   # plot x^1, x^2, ..., x^4

        y = [Xi**pow for Xi in x]
        print(y)

        plt.plot(x, y)
        plt.draw()
        #plt.show()             #this plots correctly, but blocks execution.
        plt.show(block=False)   #this creates an empty frozen window.
        _ = raw_input("Press [enter] to continue.")


if __name__ == '__main__':
    main()

PS.我忘了说,我想更新现有的窗口,每次我绘制一些东西,而不是创建一个新的。


当前回答

很多答案都被夸大了,据我所知,答案并不难理解。

如果您愿意,可以使用plt.ion(),但我发现使用plt.draw()同样有效

对于我的特定项目,我正在绘制图像,但你可以使用plot()或scatter()或其他东西来代替figimage(),这没有关系。

plt.figimage(image_to_show)
plt.draw()
plt.pause(0.001)

Or

fig = plt.figure()
...
fig.figimage(image_to_show)
fig.canvas.draw()
plt.pause(0.001)

如果你用的是实际数字。 我使用@krs013和@默认图片的答案来计算这个 希望这能让人们不必在单独的线程上发布每个人物,或者不必为了弄清楚这个问题而阅读这些小说

其他回答

您可以通过将绘图写入数组,然后在不同的线程中显示该数组来避免阻塞执行。下面是一个使用pyformulas 0.2.8中的pf.screen同时生成和显示绘图的示例:

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

fig = plt.figure()

canvas = np.zeros((480,640))
screen = pf.screen(canvas, 'Sinusoid')

start = time.time()
while True:
    now = time.time() - start

    x = np.linspace(now-2, now, 100)
    y = np.sin(2*np.pi*x) + np.sin(3*np.pi*x)
    plt.xlim(now-2,now+1)
    plt.ylim(-3,3)
    plt.plot(x, y, c='black')

    # If we haven't already shown or saved the plot, then we need to draw the figure first...
    fig.canvas.draw()

    image = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')
    image = image.reshape(fig.canvas.get_width_height()[::-1] + (3,))

    screen.update(image)

#screen.close()

结果:

免责声明:我是pyformulas的维护者。

Matplotlib:将图保存到numpy数组


下面是一个对我很有用的小技巧:

在show: plt中使用block = False参数。show(block = False) 在.py脚本末尾使用另一个plt.show()。


例子:

import matplotlib.pyplot as plt

plt.imshow(add_something)
plt.xlabel("x")
plt.ylabel("y")

plt.show(block=False)

#more code here (e.g. do calculations and use print to see them on the screen

plt.show()

注意:plt.show()是脚本的最后一行。

我花了很长时间寻找解决方案,找到了这个答案。

看起来,为了得到你(和我)想要的东西,你需要plt.ion(), plt.show()(不带block=False)和最重要的plt.pause(.001)(或任何你想要的时间)的组合。之所以需要暂停,是因为GUI事件发生在主代码休眠时,包括绘图。这可能是通过从一个睡眠线程中获取时间来实现的,所以ide可能会搞砸它-我不知道。

下面是一个在python 3.5上为我工作的实现:

import numpy as np
from matplotlib import pyplot as plt

def main():
    plt.axis([-50,50,0,10000])
    plt.ion()
    plt.show()

    x = np.arange(-50, 51)
    for pow in range(1,5):   # plot x^1, x^2, ..., x^4
        y = [Xi**pow for Xi in x]
        plt.plot(x, y)
        plt.draw()
        plt.pause(0.001)
        input("Press [enter] to continue.")

if __name__ == '__main__':
    main()

Python包drawnow允许以非阻塞的方式实时更新绘图。 它还与网络摄像头和OpenCV一起工作,例如绘制每一帧的测量值。 请看原文。

我发现plt.pause(0.001)命令是唯一需要的东西,其他什么都不需要。

Plt.show()和plt.draw()是不必要的和/或以某种方式阻塞。这是一个绘制和更新图形的代码。本质上,plt.pause(0.001)似乎最接近matlab的drawnow。

不幸的是,除非您插入input()命令,否则这些图将不是交互式的(它们会冻结),但随后代码将停止。

pl .pause(interval)命令的文档说明:

如果有活动图形,它将在暂停......之前更新并显示 这可以用于粗糙的动画。

这就是我们想要的。试试下面的代码:

import numpy as np
from matplotlib import pyplot as plt

x = np.arange(0, 51)               # x coordinates  
         
for z in range(10, 50):

    y = np.power(x, z/10)          # y coordinates of plot for animation

    plt.cla()                      # delete previous plot
    plt.axis([-50, 50, 0, 10000])  # set axis limits, to avoid rescaling
    plt.plot(x, y)                 # generate new plot
    plt.pause(0.1)                 # pause 0.1 sec, to force a plot redraw