在 matplotlib 中,有没有办法异步弹出图形? [英] in matplotlib, is there a way to pop up a figure asynchronously?
问题描述
在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屋!