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

2025-01-03 08:40:00
admin
原创
158
摘要:问题描述:在执行完 Python 解释器中的这些指令后,将出现一个带有绘图的窗口:from matplotlib.pyplot import * plot([1,2,3]) show() # other code show()不幸的是,我不知道如何在程序进行进一步计算时继续以交互方式探索所创建的图形。这有可能...

问题描述:

在执行完 Python 解释器中的这些指令后,将出现一个带有绘图的窗口:

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

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

这有可能吗?有时计算时间很长,如果在检查中间结果时进行计算会很有帮助。


解决方案 1:

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

解决方案 2:

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

from matplotlib.pyplot import show, plot

plot(1)  
show(block=False)

# your code

继续你的代码。

解决方案 3:

最好始终检查您所使用的库是否支持以非阻塞方式使用。

但是,如果您想要一个更通用的解决方案,或者没有其他办法,您可以使用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 调用)

解决方案 4:

尝试

import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.show(block=False)
# other code
# [...]

# Put
plt.show()
# at the very end of your script to make sure Python doesn't bail out
# before you finished examining.

文档show()说:

在非交互模式下,显示所有图形并阻塞,直到图形关闭;在交互模式下,除非图形是在从非交互模式更改为交互模式之前创建的(不推荐),否则它不起作用。在这种情况下,它会显示图形但不会阻塞。

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

解决方案 5:

重要提示:只是为了说明一下。我假设命令位于脚本中,并且使用例如控制台来.py调用脚本。python script.py

对我来说,一个简单的方法是:

  1. 在 show 中使用 block = False :plt.show(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()

解决方案 6:

您可能想要阅读 的matplotlib文档中的此文档,标题为:

在 Python Shell 中使用 Matplotlib

解决方案 7:

在我的例子中,我希望在计算时弹出几个窗口。作为参考,这是方法:

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 接口的相当有用的指南。

解决方案 8:

好吧,我在弄清楚非阻塞命令时遇到了很大的麻烦...但最后,我设法重新设计了“ 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! 

希望这对某人有帮助,

干杯!

解决方案 9:

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

优点:

  • 您可以随时打开、查看并关闭它。当您的应用程序运行时间较长时,这尤其方便。

  • 不会弹出任何内容,也不必打开窗口。处理大量数据时,这一点尤其方便。

  • 您的图像可供以后参考,并且在关闭图形窗口时不会丢失。

退税:

  • 我唯一能想到的就是你必须自己去查找文件夹并打开图像。

解决方案 10:

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

plt.show(0)

这将是相同的。

解决方案 11:

我还必须添加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)

解决方案 12:

在我的系统上,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:Python26libsite-packagesmatplotlibackend_bases.py:2051: DeprecationWarning: Using default event loop until function specific to this GUI is implemented
  warnings.warn(str,DeprecationWarning)

尽管脚本仍然运行。

解决方案 13:

OP 询问有关分离matplotlib图的问题。大多数答案都假设命令在 Python 解释器中执行。这里介绍的用例是我偏爱在终端(例如 bash)中测试代码,在终端中file.py运行 a,并且您希望图出现但 Python 脚本完成并返回命令提示符。

此独立文件用于multiprocessing启动一个单独的进程,以便使用 绘制数据matplotlib。主线程使用本文中提到的 退出。os._exit(1)强制主线程退出,但让子进程保持活动状态并响应,直到绘图窗口关闭。这是一个完全独立的过程。os._exit()`matplotlib`

这种方法有点像 Matlab 开发会话,其中图形窗口带有响应式命令提示符。使用这种方法,您已经失去了与图形窗口进程的所有联系,但这对于开发和调试来说没问题。只需关闭窗口并继续测试即可。

multiprocessing专为仅执行 Python 代码而设计,这可能比 更适合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

解决方案 14:

我还希望我的图能够显示运行其余代码(然后继续显示),即使出现错误也是如此(我有时使用图进行调试)。我编写了这个小技巧,以便此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如果要暂停绘图输出,请按 p(您有 5 秒钟的时间):”来自https://stackoverflow.com/questions/26704840/corner-cases-for-my-wait-for-user-input-interruption-implementation

解决方案 15:

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

解决方案 16:

在我看来,此线程中的答案提供的方法并不适用于所有系统和动画等更复杂的情况。我建议查看以下线程中 MiKTeX 的答案,其中找到了一种可靠的方法:
如何等到 matplotlib 动画结束?

解决方案 17:

这是我发现的最简单的解决方案(线程阻塞代码)

plt.show(block=False) # this avoids blocking your thread

plt.pause(1) # comment this if you do not want a time delay

# do more stuff

plt.show(block=True) # this prevents the window from closing on you

解决方案 18:

如果您想打开多个图形,同时保持它们全部打开,则此代码对我有用:

show(block=False)
draw()

解决方案 19:

虽然没有直接回答 OP 的请求,但我发布了这个解决方法,因为它可能会对处于这种情况的人有所帮助:

  • 我正在用 pyinstaller 创建 .exe,因为我无法在需要生成图表的地方安装 python,所以我需要 python 脚本来生成图表,将其保存为 .png,关闭它并继续下一个,在循环中或使用函数实现为多个图表。

为此我使用:

import matplotlib.pyplot as plt
#code generating the plot in a loop or function
#saving the plot
plt.savefig(var+'_plot.png',bbox_inches='tight', dpi=250) 
#you can allways reopen the plot using
os.system(var+'_plot.png') # unfortunately .png allows no interaction.
#the following avoids plot blocking the execution while in non-interactive mode
plt.show(block=False) 
#and the following closes the plot while next iteration will generate new instance.
plt.close() 

其中“var”标识循环中的图,因此它不会被覆盖。

解决方案 20:

我发现最好的解决方案是,在程序结束时显示所有绘图,这样程序就不必等待您关闭图形并将所有绘图放在一起,以便您可以并排检查它们。

但这样您就无法在程序运行时检查绘图。

# stuff

numFig = 1

plt.figure(numFig)
numFig += 1
plt.plot(x1, y1)

# other stuff

plt.figure(numFig)
numFig += 1
plt.plot(x2, y2)

# more stuff

plt.show()

解决方案 21:

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

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

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1989  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1446  
  在当今快速发展的IT行业中,项目管理工具的选择对于项目的成功至关重要。随着技术的不断进步,项目经理们需要更加高效、灵活的工具来应对复杂的项目需求。本文将介绍2025年IT项目经理力推的10款管理工具,帮助您在项目管理中取得更好的成果。信创国产项目管理软件 - 禅道禅道是一款国产开源的项目管理软件,禅道开源版不限人数,功...
项目管理工具   0  
  在当今快速变化的商业环境中,项目管理软件已成为企业提升效率、优化资源分配和确保项目成功的关键工具。随着技术的不断进步,市场上涌现出众多功能各异的项目管理工具,每一款都有其独特的优势和适用场景。本文将深入评测2025年最受欢迎的10款项目管理软件,帮助您根据自身需求做出明智的选择。信创国产项目管理软件 - 禅道禅道是一款...
项目管理平台   2  
  产品开发效率对于企业的竞争力至关重要。在当今复杂多变的商业环境中,如何有效提升产品开发效率成为众多企业关注的焦点。产品生命周期管理(PLM)作为一种整合产品全生命周期信息的管理理念和技术,为提升产品开发效率提供了有力的支持。通过合理运用PLM,企业能够优化流程、加强协作、提高数据管理水平,从而实现产品开发的高效运作。接...
plm开发流程软件   3  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用