在 matplotlib 中,有没有办法异步弹出图形? [英] in matplotlib, is there a way to pop up a figure asynchronously?

查看:65
本文介绍了在 matplotlib 中,有没有办法异步弹出图形?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在matplotlib中,有一种简单的方法来绘制图形而不中断脚本的控制流程吗?

In matplotlib, is there a simple way of plotting a figure without interrupting the control flow of the script?

为了清楚起见,使用伪代码,这是我要实现的目标:

Using pseudocode for clarity, here's what I'm trying to achieve:

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

当然,我可以保存这些中间图,但是我只需要快速浏览一下它们,最好是将它们实时弹出在屏幕上.

Of course, I can just savefig() these intermediate figures, but I only need a quick glance at a them and it would be the best to have them just pop up on the screen in real time.

一个可运行的示例:

#!/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"

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

Am I missing something very very basic?

推荐答案

首先,不要忘记一个简单的选择,就是使用 plt.figure(2)创建新的图形窗口,plt.figure(3) 等 如果你真的想更新现有的图形窗口,你最好用

First things first, don't forget a simple alternative is to just make new figure windows with plt.figure(2), plt.figure(3) etc. If you really want to update the existing figure window, you had better keep a handle on your lines object with

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

然后稍后您将执行以下操作:

And then later you would be doing something like:

h[0].set_data(some_new_results)
ax.figure.canvas.draw()

至于问题的实质,如果您仍在与这篇文章作斗争,请继续阅读..

As for the real meat of the question, if you're still battling with this read on..

如果您希望 plt.show() 非阻塞,您需要启用交互模式.要修改您的可运行示例,以便 现在做其他事情" 将立即打印,而不是等待图形窗口关闭,请执行以下操作:

You need to enable interactive mode if you want plt.show() to be non-blocking. To modify your runnable example so that "doing something else now" would print immediately, as opposed to waiting for the figure window to be closed, the following would do:

#!/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...')

然而,这只是触及事物的表面——一旦你开始想要在与情节交互的同时做背景工作,就会有很多复杂的事情.这是使用本质上是状态机进行绘画的自然结果,它不能与面向对象环境中的线程和编程相提并论.

However, this is just scratching the surface of things - there are many complications once you start wanting to do background work while interacting with the plots. This is a natural consequence of painting with what's essentially a state machine, it doesn't rub well with threading and programming in an object-oriented environment.

  • 昂贵的计算将不得不进入工作线程(或进入子进程)以避免冻结 GUI.
  • Queue 应该用于以线程安全的方式传递输入数据并从辅助函数中获取结果.
  • 根据我的经验,在工作线程中调用 draw() 是不安全的,因此您还需要设置一种方法来安排重绘.
  • 不同的后端可能开始做奇怪的事情,TkAgg 似乎是唯一一个 100% 工作的后端(请参阅
  • Expensive calculations will have to go into worker threads (or alternatively into subprocesses) to avoid freezing the GUI.
  • Queue should be used to pass input data and get results out of the worker functions in a thread-safe way.
  • In my experience, it is not safe to call draw() in the worker thread so you also need to set up a way to schedule a repaint.
  • Different backends may start to do strange things and TkAgg seems to be the only one which works 100% (see here).

最简单和最好的解决方案不是使用 vanilla python 解释器,而是使用 ipython -pylab(正如 ianalis 正确建议的那样),因为他们已经找到了大多数需要的技巧让互动的东西顺利工作.无需 ipython / pylab 即可完成此操作,但这是大量的额外工作.

The easiest and best solution is not to use the vanilla python interpreter, but to use ipython -pylab (as ianalis has rightly suggested), because they have already figured out most of the tricks needed to get interactive stuff working smoothly. It can be done without ipython/pylab but it's a significant amount of extra work.

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

Note: I still often like to farm off worker threads whilst using ipython and pyplot GUI windows, and to get threading working smoothly I also need to use another commandline argument ipython -pylab -wthread. I'm on python 2.7.1+ with matplotlib v1.1.0, your mileage may vary. Hope this helps!

Ubuntu用户注意事项:相当长一段时间以来,版本库仍在v0.99上,值得升级你的 matplotlib 因为有 在v1.0版本中进行了许多改进,其中包括 Bugfix马拉松,以及对 show()行为的重大更改.

Note for Ubuntu users: The repositories are still back on v0.99 for quite some time now, it is worth upgrading your matplotlib because there were many improvements coming up to the v1.0 release including a Bugfix marathon, and major changes to the behaviour of show().

这篇关于在 matplotlib 中,有没有办法异步弹出图形?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆