在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()
创建的图形。
这种情况有可能吗?有时候计算需要很长时间,如果在检查中间结果的同时能够继续进行计算将会很有帮助。
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)
在我的系统上,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)
matplotlib
图。大多数答案都假设在Python解释器中执行命令。这里介绍的用例是我更喜欢在终端(例如bash)中测试代码,其中运行file.py
并希望图形出现,但Python脚本完成并返回到命令提示符。multiprocessing
启动一个单独的进程来绘制matplotlib
数据。主线程使用this帖子中提到的os._exit(1)
退出。 os._exit()
强制主线程退出,但保留matplotlib
子进程活动并响应,直到关闭绘图窗口。它完全是一个单独的进程。#!/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
的图形窗口仍然保持响应,具有缩放、平移和其他按钮,因为它是一个独立的进程。ps ax|grep -v grep |grep file.py
。但是,正如那里描述的那样,
sys.exit()并没有像预期的那样终止父进程,直到我关闭了子窗口。另一方面,使用上面示例中的
os._exit(0)` 确实起作用了。 - ttsesmwith
语句内的任何图表都能够实现此功能。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
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
这是我找到的最简单的解决方案(线程阻塞代码)
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
show(block=False)
draw()
# 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()
虽然没有直接回答OP的问题,但我发布这个解决方法,因为它可能会帮助到处于这种情况下的某些人:
为此,我使用:
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"用于标识绘图,以防止其被覆盖。
ion()
打开交互模式可以解决问题。 - H. Brandsmeieros.fork()
,但请记住,使用os.fork()
可能会很棘手,因为您正在通过复制旧进程来创建新进程。 - Trevor Boyd Smithos.fork
方法。 - Redsbefall