有没有办法分离matplotlib图,使计算可以继续?

在Python解释器中的这些指令之后,得到一个带有图的窗口:

from matplotlib.pyplot import * plot([1,2,3]) show() # other code 

不幸的是,我不知道如何在程序做进一步的计算时继续交互式地探索show()创build的graphics。

有没有可能? 有时计算时间很长,如果在检查中间结果的时候进行计算,将会有所帮助。

使用matplotlib的调用将不会阻止:

使用draw()

 from matplotlib.pyplot import plot, draw, show plot([1,2,3]) draw() print 'continue computation' # at the end call show to ensure window won't close. show() 

使用交互模式:

 from matplotlib.pyplot import plot, ion, show ion() # enables interactive mode plot([1,2,3]) # result shows immediatelly (implicit draw()) print 'continue computation' # at the end call show to ensure window won't close. show() 

使用关键字“块”来覆盖阻止行为,例如

 from matplotlib.pyplot import show, plot plot(1) show(block=False) # your code 

继续你的代码。

如果以非阻塞方式支持使用情况,最好始终检查使用的库。

但是如果你想要一个更通用的解决scheme,或者没有其他方法,可以使用python中包含的多处理模块在分离的进程中运行任何块。 计算将继续:

 from multiprocessing import Process from matplotlib.pyplot import plot, show def plot_graph(*args): for data in args: plot(data) show() p = Process(target=plot_graph, args=([1, 2, 3],)) p.start() print 'yay' print 'computation continues...' print 'that rocks.' print 'Now lets wait for the graph be closed to continue...:' p.join() 

这有启动一个新的过程的开销,有时难以debugging复杂的情况下,所以我更喜欢另一种解决scheme(使用matplotlib的非阻塞API调用 )

尝试

 from matplotlib.pyplot import * plot([1,2,3]) show(block=False) # other code # [...] # Put show() # at the very end of your script # to make sure Python doesn't bail out # before you finished examining. 

show()文档说:

在非交互模式下,显示所有数字并阻止,直到数字被closures; 在交互模式下,除非数字是在从非交互模式转换到交互模式之前创build的,否则不起作用(不推荐)。 在这种情况下,它显示的数字,但不会阻止。

单个实验性关键字参数block可以设置为TrueFalse来覆盖上面描述的阻止行为。

您可能需要在matplotlib的文档中阅读这个文档,标题为:

在python shell中使用matplotlib

那么,我很难找出非阻塞命令.​​..但最后,我设法重做了“ 食谱/ Matplotlib /animation – animation选定的剧情元素 ”的例子,所以它与线程( 并在线程之间传递数据)通过全局variables或通过多进程Pipe )在Ubuntu 10.04上的Python 2.6.5。

脚本可以在这里find: Animating_selected_plot_elements-thread.py – 否则粘贴下面( 与较less的意见 ),以供参考:

 import sys import gtk, gobject import matplotlib matplotlib.use('GTKAgg') import pylab as p import numpy as nx import time import threading ax = p.subplot(111) canvas = ax.figure.canvas # for profiling tstart = time.time() # create the initial line x = nx.arange(0,2*nx.pi,0.01) line, = ax.plot(x, nx.sin(x), animated=True) # save the clean slate background -- everything but the animated line # is drawn and saved in the pixel buffer background background = canvas.copy_from_bbox(ax.bbox) # just a plain global var to pass data (from main, to plot update thread) global mypass # http://docs.python.org/library/multiprocessing.html#pipes-and-queues from multiprocessing import Pipe global pipe1main, pipe1upd pipe1main, pipe1upd = Pipe() # the kind of processing we might want to do in a main() function, # will now be done in a "main thread" - so it can run in # parallel with gobject.idle_add(update_line) def threadMainTest(): global mypass global runthread global pipe1main print "tt" interncount = 1 while runthread: mypass += 1 if mypass > 100: # start "speeding up" animation, only after 100 counts have passed interncount *= 1.03 pipe1main.send(interncount) time.sleep(0.01) return # main plot / GUI update def update_line(*args): global mypass global t0 global runthread global pipe1upd if not runthread: return False if pipe1upd.poll(): # check first if there is anything to receive myinterncount = pipe1upd.recv() update_line.cnt = mypass # restore the clean slate background canvas.restore_region(background) # update the data line.set_ydata(nx.sin(x+(update_line.cnt+myinterncount)/10.0)) # just draw the animated artist ax.draw_artist(line) # just redraw the axes rectangle canvas.blit(ax.bbox) if update_line.cnt>=500: # print the timing info and quit print 'FPS:' , update_line.cnt/(time.time()-tstart) runthread=0 t0.join(1) print "exiting" sys.exit(0) return True global runthread update_line.cnt = 0 mypass = 0 runthread=1 gobject.idle_add(update_line) global t0 t0 = threading.Thread(target=threadMainTest) t0.start() # start the graphics update thread p.show() print "out" # will never print - show() blocks indefinitely! 

希望这有助于某人,
干杯!

在我的情况下,我想有几个窗口popup,因为他们正在计算。 作为参考,这是方式:

 from matplotlib.pyplot import draw, figure, show f1, f2 = figure(), figure() af1 = f1.add_subplot(111) af2 = f2.add_subplot(111) af1.plot([1,2,3]) af2.plot([6,5,4]) draw() print 'continuing computation' show() 

PS。 matplotlib的OO接口的一个非常有用的指南 。

如果你在控制台工作,即IPython你可以使用plt.show(block=False)正如其他答案中指出的那样。 但是如果你懒惰,你可以input:

 plt.show(0) 

这将是相同的。

在很多情况下, 将图像保存为硬盘上的.png文件会更方便 。 这是为什么:

优点:

  • 你可以打开它,看看它,并在任何时候closures它。 当您的应用程序运行很长时间时,这特别方便。
  • 没有什么东西popup来,你不必强迫窗户打开。 当你处理很多数字时,这是特别方便的。
  • 您的图像可供以后参考,closures数字窗口时不会丢失。

退税:

  • 我唯一能想到的是,你将不得不去find文件夹,并自己打开图像。

一个简单的方法适用于我:

  1. 使用block = False里面显示: plt.show(block = False)
  2. 在.py脚本的末尾使用另一个 show()。

例:

 plt.imshow(add_something) plt.colorbar() plt.xlabel("true ") plt.ylabel("predicted ") plt.title(" the matrix") plt.show(block = False) # Add block = False ########### OTHER CALCULATIONS AND CODE ### plt.show() # last line of my script 

在我的系统show()不阻塞,虽然我希望脚本等待用户与graphics交互(并收集数据使用'pick_event'callback),然后再继续。

为了阻止执行,直到绘图窗口closures,我使用了以下内容:

 fig = plt.figure() ax = fig.add_subplot(1,1,1) ax.plot(x,y) # set processing to continue when window closed def onclose(event): fig.canvas.stop_event_loop() fig.canvas.mpl_connect('close_event', onclose) fig.show() # this call does not block on my system fig.canvas.start_event_loop_default() # block here until window closed # continue with further processing, perhaps using result from callbacks 

但是请注意,canvas.start_event_loop_default()会产生以下警告:

 C:\Python26\lib\site-packages\matplotlib\backend_bases.py:2051: DeprecationWarning: Using default event loop until function specific to this GUI is implemented warnings.warn(str,DeprecationWarning) 

尽pipe脚本仍然运行。

即使有错误(我有时使用图进行debugging),我也想让我的图显示运行代码的其余部分(然后继续显示)。 我编写了这个小黑客,以便这个语句里面的任何图表都是这样的。

对于生产代码,这可能有点太不标准,也不可取。 这个代码中可能有很多隐藏的“陷阱”。

 from contextlib import contextmanager @contextmanager def keep_plots_open(keep_show_open_on_exit=True, even_when_error=True): ''' To continue excecuting code when plt.show() is called and keep the plot on displaying before this contex manager exits (even if an error caused the exit). ''' import matplotlib.pyplot show_original = matplotlib.pyplot.show def show_replacement(*args, **kwargs): kwargs['block'] = False show_original(*args, **kwargs) matplotlib.pyplot.show = show_replacement pylab_exists = True try: import pylab except ImportError: pylab_exists = False if pylab_exists: pylab.show = show_replacement try: yield except Exception, err: if keep_show_open_on_exit and even_when_error: print "*********************************************" print "Error early edition while waiting for show():" print "*********************************************" import traceback print traceback.format_exc() show_original() print "*********************************************" raise finally: matplotlib.pyplot.show = show_original if pylab_exists: pylab.show = show_original if keep_show_open_on_exit: show_original() # *********************** # Running example # *********************** import pylab as pl import time if __name__ == '__main__': with keep_plots_open(): pl.figure('a') pl.plot([1,2,3], [4,5,6]) pl.plot([3,2,1], [4,5,6]) pl.show() pl.figure('b') pl.plot([1,2,3], [4,5,6]) pl.show() time.sleep(1) print '...' time.sleep(1) print '...' time.sleep(1) print '...' this_will_surely_cause_an_error 

如果/当我执行一个合适的“保持打开的情节(即使发生错误)并允许显示新的情节”,如果没有用户干扰告知它(为了批处理执行的目的),我会希望脚本正确地退出。

我可能会使用类似超时问题的问题“脚本结束!\ n如果您希望绘图输出暂停(您有5秒钟), 请按 p:”from https://stackoverflow.com/questions/26704840/corner用于等待用户input中断的实现; 。

在我看来,在这个线程中的答案提供了不适用于每个系统和更复杂的情况,如animation的方法。 我build议看看在以下线程MikeTex的答案,其中一个健壮的方法已被发现: 如何等待,直到matplotlibanimation结束?

如果我正确地理解了这个问题,使用Ipython(或Ipython QT或Ipython笔记本)将允许您交互式地处理图表,而计算在后台执行。 http://ipython.org/

我还必须添加plt.pause(0.001)到我的代码,真正使它在for循环内工作(否则它只会显示第一个和最后一个图):

 import matplotlib.pyplot as plt plt.scatter([0], [1]) plt.draw() plt.show(block=False) for i in range(10): plt.scatter([i], [i+1]) plt.draw() plt.pause(0.001) 
 plt.figure(1) plt.imshow(your_first_image) plt.figure(2) plt.imshow(your_second_image) plt.show(block=False) # That's important raw_input("Press ENTER to exist") # Useful when you run your Python script from the terminal and you want to hold the running to see your figures until you press Enter 

如果你想打开多个数字,而保持全部打开,这个代码为我工作:

 show(block=False) draw()