在matplotlib中,是否有异步弹出图形的方法?

在matplotlib中,是否有异步弹出图形的方法?,matplotlib,Matplotlib,在matplotlib中,是否有一种简单的方法可以在不中断脚本控制流的情况下绘制图形 为了清晰起见,使用伪代码,我尝试实现以下目标: fig1 = figure() fig1.plot_a_figure(datasets) for dataset in datasets: results = analyze(dataset) # this takes several minutes update(fig1) pop_up_another_figure(results)

在matplotlib中,是否有一种简单的方法可以在不中断脚本控制流的情况下绘制图形

为了清晰起见,使用伪代码,我尝试实现以下目标:

fig1 = figure()
fig1.plot_a_figure(datasets)

for dataset in datasets:
   results = analyze(dataset)    # this takes several minutes
   update(fig1)
   pop_up_another_figure(results) # would like to have a look at this one
                                  # while the next dataset is being processed
当然,我可以只保存这些中间数字,但我只需要快速浏览一下它们,最好让它们实时出现在屏幕上

编辑:一个可运行的示例:

#!/usr/bin/python
import pylab as plb
import matplotlib.pyplot as plt

fig1=plt.figure(1)
ax = fig1.add_subplot(1,1,1)

ax.plot([1,2,3],[4,5,6],'ro-')

#fig1.show()  # this does not show a figure if uncommented
plt.show()    # until the plot window is closed, the next line is not executed

print "doing something else now"

我是否遗漏了一些非常基本的东西?

最简单的解决方案可能是使用IPython作为python shell。使用-pylab选项运行它

ipython -pylab

首先,不要忘记一个简单的替代方法是使用
plt.figure(2)
plt.figure(3)
等创建新的图形窗口。如果您真的想更新现有的图形窗口,最好使用对象保留线条上的句柄

h = ax.plot([1,2,3],[4,5,6],'ro-')
然后你会做一些类似的事情:

h[0].set_data(some_new_results)
ax.figure.canvas.draw()
至于问题的实质,如果你还在为这个争论不休,那就继续读下去


如果希望
plt.show()
为非阻塞模式,则需要启用交互模式。要修改可运行示例,使“立即执行其他操作”立即打印,而不是等待图形窗口关闭,请执行以下操作:

#!/usr/bin/python
import pylab as plb
import matplotlib.pyplot as plt

fig1=plt.figure(1)
ax = fig1.add_subplot(1,1,1)

ax.plot([1,2,3],[4,5,6],'ro-')

#fig1.show()  # this does not show a figure if uncommented
plt.ion()     # turns on interactive mode
plt.show()    # now this should be non-blocking

print "doing something else now"
raw_input('Press Enter to continue...')
然而,这仅仅是表面的东西-有很多复杂的事情一旦你开始想做背景工作,同时与情节互动。这是使用状态机绘制的自然结果,它与面向对象环境中的线程和编程不太协调

  • 昂贵的计算必须进入工作线程(或者子进程),以避免冻结GUI
  • Queue
    应用于以线程安全的方式传递输入数据并从辅助函数中获取结果
  • 根据我的经验,在工作线程中调用
    draw()
    是不安全的,因此您还需要设置一种方法来安排重新绘制
  • 不同的后端可能会开始做奇怪的事情,
    TkAgg
    似乎是唯一一个100%工作的后端(请参阅)
最简单和最好的解决方案不是使用普通的python解释器,而是使用
ipython-pylab
(正如ianalis正确地建议的那样),因为他们已经找到了让交互工作顺利进行所需的大部分技巧。它可以在不使用ipython的情况下完成,但这是一项大量的额外工作

注意:在使用ipython和pyplot GUI窗口时,我仍然经常喜欢将工作线程分出去,为了使线程顺利工作,我还需要使用另一个命令行参数
ipython-pylab-wthread
。我使用的是
python 2.7.1+
matplotlib v1.1.0
,您的里程可能会有所不同。希望这有帮助


Ubuntu用户注意:在相当长的一段时间内,存储库仍然在v0.99上运行,值得您使用
matplotlib
,因为v1.0版本即将发布,包括一个错误修复马拉松,以及
show()
行为的重大更改

我以为
show()
已经这么做了。您可以创建任意数量的图形,show()每个图形都将在代码运行时保持显示。你能发布一个可运行的示例来演示这个问题吗?@Paul:添加了一个示例。我错过了一些琐碎的事情吗?不,你绝对没有错过任何琐碎的事情。我刚刚看到这么多的情节意外地同时出现,我认为有一些线程正在进行,show()不会获得锁。阅读这篇文章:我可以想出三种方法:首先,如果你不关心绘图是否是交互式的,你可以像你建议的那样保存一幅图像,但随后可以使用
os.startfile()
轻松启动该图像的查看器。如果您希望它是交互式的,并且不介意将数据写入磁盘,那么可以使用另一个python脚本
subprocess.Popen()。第三种方法是尝试真正理解matplotlib是如何管理线程的..使用plt.ion()尝试了您的示例。对我不起作用,plt.show()仍在阻止它。我使用的是Ubuntu 10.04、python 2.6.5和matplotlib 0.99。这是不是太旧了?也许是太旧了:他们对v1.0版的
show()
的实现做了相当大的修改(参见此处)。如果将
plt.ion()
行向上移动到脚本顶部,即在
导入matplotlib.pyplot作为plt
之后,会得到什么?调用函数
matplotlib.get\u backend()
的结果是什么?get\u backend()返回TkAgg,如果plt.ion()是脚本的第一行,则不会有任何更改。是否
ax.figure.canvas.draw()是阻塞/同步调用?我在任何地方都找不到那个信息。如果你知道或有一个参考,解释这一点,将不胜感激。