在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()创建的图形。
这可能吗?有时计算很长,如果在检查中间结果时进行计算将会有所帮助。
当前回答
最好总是检查您正在使用的库是否支持以非阻塞的方式使用。
但是如果你想要一个更通用的解决方案,或者如果没有其他方法,你可以通过使用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()
这有启动新进程的开销,而且在复杂的场景下有时更难调试,因此我更喜欢其他解决方案(使用matplotlib的非阻塞API调用)
其他回答
使用matplotlib调用不会阻塞:
使用画():
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()
在我的系统上,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)
尽管脚本仍然在运行。
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
重要提示:只是为了澄清一些事情。我假设命令在.py脚本中,脚本是使用python script.py从控制台调用的。
对我来说,一个简单的方法是:
使用block = False在里面显示:plt。show(block = False) 在.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()
嗯,我在搞清楚非阻塞命令方面遇到了很大的困难……但最后,我成功地重做了“Cookbook/Matplotlib/Animations -动画选定的绘图元素”的例子,所以它可以在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!
希望这能帮助到一些人, 干杯!