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

python matplotlib plot

204429 观看

18回复

2309 作者的声誉

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

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

不幸的是,我不知道如何继续以交互方式探索show()在程序进行进一步计算时创建的图形。

有可能吗?有时计算很长,如果他们在检查中间结果期间继续进行计算会有所帮助。

作者: meteore 的来源 发布者: 2009 年 1 月 19 日

回应 (18)


29

163237 作者的声誉

如果它以非阻塞方式支持使用,最好始终检查您正在使用的库。

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

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()

这已推出一个新的进程的开销,有时难以在复杂的场景进行调试,所以我更喜欢其他的解决方案(使用matplotlib非阻塞API调用

作者: nosklo 发布者: 19.01.2009 04:40

199

163237 作者的声誉

决定

使用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()
作者: nosklo 发布者: 19.01.2009 04:52

10

163237 作者的声誉

您可能希望在文档中阅读本matplotlib文档,标题为:

在python shell中使用matplotlib

作者: nosklo 发布者: 19.01.2009 05:00

8

2309 作者的声誉

在我的情况下,我想在计算时弹出几个窗口。作为参考,这是方式:

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接口非常有用的指南

作者: meteore 发布者: 21.01.2009 02:05

6

21424 作者的声誉

好吧,我很难搞清楚非阻塞命令.​​.....但最后,我设法重做了“ Cookbook / Matplotlib / Animations - 动画选定的绘图元素 ”示例,因此它适用于线程(并在线程之间传递数据)通过全局变量,或通过多Pipe进程)在Ubuntu 10.04上的Python 2.6.5上。

脚本可以在这里找到:Animating_selected_plot_elements-thread.py - 否则粘贴在下面(注释较少)以供参考:

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! 

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

作者: sdaau 发布者: 10.11.2010 09:55

2

21 作者的声誉

在我的系统上show()没有阻塞,虽然我希望脚本在继续之前等待用户与图形交互(并使用'pick_event'回调收集数据)。

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

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)

虽然脚本仍在运行。

作者: Andrew 发布者: 17.03.2011 05:06

119

3586 作者的声誉

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

from matplotlib.pyplot import show, plot

plot(1)  
show(block=False)

# your code

继续你的代码。

作者: Jan 发布者: 13.11.2012 01:40

21

16928 作者的声誉

尝试

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()文件说:

在非交互模式下,显示所有数字并阻止,直到数字关闭; 在交互模式下,除非在从非交互模式更改为交互模式之前创建数字(不推荐),否则它无效。在这种情况下,它显示数字但不阻止。

可以将单个实验关键字参数block设置为TrueFalse覆盖上述阻塞行为。

作者: Nico Schlömer 发布者: 18.01.2013 11:53

5

1036 作者的声誉

在许多情况下,将图像保存为硬盘驱动器上的.png文件更方便。原因如下:

好处:

  • 您可以打开它,查看它并在此过程中随时关闭它。当您的应用程序运行很长时间时,这非常方便。
  • 没有任何东西弹出,你不会被迫打开窗户。当你处理许多数字时,这是特别方便的。
  • 您的图像可供以后参考,关闭图形窗口时不会丢失。

退税:

  • 我唯一能想到的是你必须自己去查找文件夹并打开图像。
作者: elgehelge 发布者: 18.12.2013 06:21

3

1556 作者的声誉

我还希望我的绘图显示运行其余代码(然后继续显示),即使出现错误(我有时会使用绘图进行调试)。我编写了这个小小的黑客,以便这个with语句中的任何图表都是这样的。

这可能有点太不标准,不适用于生产代码。这段代码中可能存在很多隐藏的“陷阱”。

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:”来自https://stackoverflow.com/questions/26704840/corner -cases-for-my-wait-for-user-input-interrupt-implementation

作者: Simon Streicher 发布者: 04.11.2014 12:14

1

304 作者的声誉

在我看来,这个帖子中的答案提供的方法不适用于每个系统以及动画等更复杂的情况。我建议在下面的线程中查看MiKTeX的答案,其中找到了一个健壮的方法: 如何等到matplotlib动画结束?

作者: MikeTeX 发布者: 27.12.2015 06:17

5

16792 作者的声誉

如果您在控制台中工作,即IPython您可以plt.show(block=False)在其他答案中指出。但如果你很懒,你可以输入:

plt.show(0)

哪个都一样。

作者: Anton Protopopov 发布者: 18.01.2016 11:11

0

529 作者的声誉

如果你想打开多个数字,同时保持它们全部打开,这段代码对我有用:

show(block=False)
draw()
作者: DomDev 发布者: 16.09.2016 03:11

4

1581 作者的声誉

我还必须添加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)
作者: Martin Pecka 发布者: 09.11.2016 02:16

2

398 作者的声誉

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
作者: thanhtang 发布者: 21.02.2017 06:27

9

9645 作者的声誉

重要提示:只是为了说清楚。我假设命令在.py脚本中,并且例如python script.py从控制台调用脚本。

一个适合我的简单方法是:

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

script.py文件示例

plt.imshow(*something*)                                                               
plt.colorbar()                                                                             
plt.xlabel("true ")                                                                   
plt.ylabel("predicted ")                                                              
plt.title(" the matrix")  

# Add block = False                                           
plt.show(block = False)

################################
# OTHER CALCULATIONS AND CODE HERE ! ! !
################################

# the next command is the last line of my script
plt.show()

作者: serafeim 发布者: 08.03.2017 02:37

0

45 作者的声誉

OP要求关于拆分matplotlib地块。大多数答案都假定在python解释器中执行命令。这里介绍的用例是我倾向于在终端(例如bash)中测试代码,其中a file.py运行并且你想要绘图,但是python脚本要完成并返回到命令提示符。

此独立文件用于multiprocessing启动单独的绘制数据的过程matplotlib。主线程退出使用os._exit(1)中提到的这个职位。该os._exit()主力退出,但留下的matplotlib子进程还活着,直到响应情节窗口关闭。这完全是一个单独的过程。

这种方法有点像Matlab开发会话,图形窗口提供响应式命令提示符。使用这种方法,您已经失去了与图窗口过程的所有联系,但是,这对于开发和调试是可以的。只需关闭窗口并继续测试。

multiprocessing是专为python-only代码执行而设计的,它可能比它更适合subprocessmultiprocessing是跨平台的,所以这应该适用于Windows或Mac,几乎没有调整。无需检查基础操作系统。这是在linux,Ubuntu 18.04LTS上测试的。

#!/usr/bin/python3

import time
import multiprocessing
import os

def plot_graph(data):
    from matplotlib.pyplot import plot, draw, show
    print("entered plot_graph()")
    plot(data)
    show() # this will block and remain a viable process as long as the figure window is open
    print("exiting plot_graph() process")

if __name__ == "__main__":
    print("starting __main__")
    multiprocessing.Process(target=plot_graph, args=([1, 2, 3],)).start()
    time.sleep(5)
    print("exiting main")
    os._exit(0) # this exits immediately with no cleanup or buffer flushing

运行file.py会打开一个数字窗口,然后__main__退出,但multiprocessing+ matplotlib数字窗口仍然保持对缩放,平移和其他按钮的响应,因为它是一个独立的过程。

使用以下命令检查bash命令提示符下的进程:

ps ax|grep -v grep |grep file.py

作者: Marc Compere 发布者: 11.07.2019 05:43

0

467 作者的声誉

使用plt.show(block=False),并在脚本调用结束时使用plt.show()

这将确保在脚本完成时不会关闭窗口。

作者: Ken Mueller 发布者: 18.08.2019 02:25
32x32