Pythonインタープリターでのこれらの指示の後、プロットのあるウィンドウが表示されます。
from matplotlib.pyplot import *
plot([1,2,3])
show()
# other code
残念ながら、プログラムがさらに計算を行っている間、show()
によって作成された図をインタラクティブに探索し続ける方法がわかりません。
まったく可能ですか?計算が長い場合があり、中間結果の検査中に計算を進めると役立つ場合があります。
ブロックしない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()
キーワード 'block'を使用して、ブロック動作をオーバーライドします。
from matplotlib.pyplot import show, plot
plot(1)
show(block=False)
# your code
コードを続行します。
non-blockingの方法での使用をサポートしている場合は、使用しているライブラリを常に確認することをお勧めします。
しかし、より一般的なソリューションが必要な場合、または他の方法がない場合は、Pythonに含まれている multprocessing
モジュールを使用して、分離されたプロセスでブロックするものを実行できます。計算は続行されます:
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
の nonblocking 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()
documentation 言います:
非インタラクティブモードでは、すべての図を表示し、図が閉じるまでブロックします。インタラクティブモードでは、非インタラクティブモードからインタラクティブモードに変更する前に数値を作成しない限り、効果はありません(推奨されません)。その場合、図は表示されますがブロックされません。
単一の実験的なキーワード引数
block
をTrue
またはFalse
に設定して、上記のブロック動作をオーバーライドできます。
次のタイトルのmatplotlib
のドキュメントでこのドキュメントを読むことをお勧めします。
重要:ただ明確にするため。コマンドは.py
スクリプト内にあり、スクリプトは例えばコンソールからpython script.py
。
私のために働く簡単な方法は次のとおりです。
例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()
私の場合、計算中にいくつかのウィンドウをポップアップ表示したかったのです。参考までに、これは次の方法です。
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インターフェイスのガイド 。
さて、非ブロックコマンドを理解するのは非常に困難でした...しかし最終的に、「 Cookbook/Matplotlib/Animations-選択したプロット要素のアニメーション化 」の例を修正し、スレッドで動作するようになりました(、グローバル変数またはマルチプロセスPipe
を介してスレッド間でデータを渡します)Python 2.6.5 on Ubuntu 10.04。
スクリプトは次の場所にあります。 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!
これが誰かを助けることを願って、
乾杯!
コンソールで作業している場合、つまりIPython
は、他の回答で指摘されているようにplt.show(block=False)
を使用できます。しかし、怠け者の場合は、次のように入力できます。
plt.show(0)
どちらも同じです。
多くの場合、これは画像を保存するまでの方が便利ハードドライブ上の.pngファイルとしてです。その理由は次のとおりです。
利点:
欠点:
また、コードに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)
また、エラーが発生した場合でも、プロットが表示されるようにして、残りのコードを実行します(その後、表示し続けます)(デバッグにプロットを使用することがあります)。この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 __== '__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秒あります):" from https://stackoverflow.com/questions/26704840/corner-cases-for-my-wait-for-user-input-interruption-implementation 。
私のシステムでは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
私の意見では、このスレッドの答えは、すべてのシステムやアニメーションなどのより複雑な状況では機能しないメソッドを提供します。次のスレッドでMiKTeXの答えを見ることをお勧めします。ここで、堅牢なメソッドが見つかりました。 matplotlibアニメーションが終了するまで待つ方法
OPは、matplotlib
プロットのデタッチについて尋ねます。ほとんどの回答は、pythonインタープリター内からのコマンド実行を前提としています。ここで紹介するユースケースは、file.py
が実行され、プロットを表示したいが、pythonスクリプトを実行するターミナル(bashなど)でコードをテストするための私の好みです。完了してコマンドプロンプトに戻ります。
このスタンドアロンファイルは、multiprocessing
を使用して、matplotlib
でデータをプロットするための別のプロセスを起動します。メインスレッドは、 this postで説明されているos._exit(1)
を使用して終了します。 os._exit()
はmainを強制的に終了しますが、プロットウィンドウが閉じるまでmatplotlib
子プロセスは生きたままで応答します。それは完全に別のプロセスです。
このアプローチは、レスポンシブコマンドプロンプトを表示するFigureウィンドウを使用したMatlab開発セッションに少し似ています。このアプローチを使用すると、Figureウィンドウプロセスとのすべての接続が失われますが、開発とデバッグには問題ありません。ウィンドウを閉じてテストを続けてください。
multiprocessing
はPythonのみのコード実行用に設計されており、おそらくsubprocess
よりも適しています。 multiprocessing
はクロスプラットフォームであるため、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 __== "__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
を実行すると、Figureウィンドウが表示され、その後__main__
は終了しますが、multiprocessing
+ matplotlib
のFigureウィンドウは、独立したプロセスであるため、ズーム、パン、その他のボタンで応答し続けます。
Bashコマンドのプロンプトでプロセスを確認します:
ps ax|grep -v grep |grep file.py
plt.show(block=False)
を使用し、スクリプトの最後でplt.show()
を呼び出します。
これにより、スクリプトの終了時にウィンドウが閉じられなくなります。
更新(Windows 10上のpython 3.6.5)は次のとおりです。
私はあらゆる種類の組み合わせを試しました-私が見つけた最も簡単なのは、各プロットの後にpause(0.01)
を使用することです-中間プロットにshow()
を必要としません-最後に単一のshow()
を使用すると、終了前に最終プロットを見ることができます.
例として、さまざまな配列サイズの速度を確認するために使用するコードを少し紹介します-プロットされた値が高いほど速度が速くなります... 10個のオーバーレイされたプロットがあります...
from pylab import *
import matplotlib.pyplot as plt
from time import *
ttot=clock();
mmax=6;npts=20;nplts=10;
x=[int(a+0.5) for a in 10**linspace(0,mmax,npts)]
for nrun in range(nplts):
j=0;aa=1;bb=1;b=1;
tim=zeros(npts)
for n in x:
aa=Rand(n);bb=aa;b=aa;
if n<100:m=10000
Elif n<5000:m=1000
Elif n<20000:m=100
else:m=100
tt=clock()
for ii in range(1,m+1):
b=aa*bb+aa
tt1=clock()-tt
tim[j]=tt1/n/m
j=j+1
print(n,2/(tt1/n/m)/1e6);
plt.semilogx(x,2/tim/1e6)
pause(0.01)
print(clock()-ttot)
show()
すべてを開いたまま複数の図を開きたい場合、このコードはうまくいきました:
show(block=False)
draw()