Czy istnieje sposób na odłączenie Wykresów matplotlib, aby obliczenia mogły być kontynuowane?

Po tych instrukcjach w interpreterze Pythona pojawia się okno z wykresem:

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

Niestety, Nie wiem, jak dalej interaktywnie badać figurę stworzoną przez show() podczas gdy program wykonuje dalsze obliczenia.

Czy to w ogóle możliwe? Czasami obliczenia są długie i pomocne byłoby, gdyby postępowały podczas badania wyników pośrednich.
Author: Anton Protopopov, 2009-01-19

18 answers

Użyj wywołań matplotlib, które nie blokują:

Używając 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()

Używanie trybu interaktywnego:

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()
 174
Author: nosklo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-26 23:09:47

Użyj słowa kluczowego 'block', aby nadpisać zachowanie blokowania, np.

from matplotlib.pyplot import show, plot

plot(1)  
show(block=False)

# your code

Aby kontynuować kod.

 113
Author: Jan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-26 16:35:45

Lepiej zawsze sprawdzić bibliotekę, której używasz, jeśli obsługuje ona użycie w sposób nieblokujący.

Ale jeśli chcesz bardziej ogólnego rozwiązania, lub jeśli nie ma innego sposobu, możesz uruchomić wszystko, co blokuje oddzielony proces za pomocą multprocessing Moduł zawarty w Pythonie. Obliczenia będą kontynuowane:

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

To ma na głowie uruchomienie nowego procesu i czasami jest trudniejsze do debugowania w złożonych scenariuszach, więc wolałbym inne rozwiązanie (użycie matplotlib ' S nieblokujące wywołania API )

 26
Author: nosklo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:38

Spróbuj

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.

The show() Dokumentacja mówi:

W trybie nieinteraktywnym Wyświetlaj wszystkie figury i blokuj je do momentu zamknięcia; w trybie interaktywnym nie ma to wpływu, chyba że figury zostały utworzone przed zmianą z trybu nieinteraktywnego na interaktywny (nie zaleca się). W takim przypadku wyświetla dane, ale nie blokuje.

Pojedynczy eksperymentalny argument słowa kluczowego, block, może być ustawiony na True lub False, aby nadpisać blokowanie zachowanie opisane powyżej.

 20
Author: Nico Schlömer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-02 10:29:47

Możesz przeczytać ten dokument w dokumentacji matplotlib, zatytułowanej:

Używanie matplotlib w powłoce Pythona

 10
Author: nosklo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-19 17:00:04

W moim przypadku chciałem mieć kilka okien wyskakujących podczas ich obliczania. Dla odniesienia, jest to sposób:

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. Bardzo przydatny przewodnik po interfejsie oo matplotlib .

 7
Author: meteore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-11 22:13:17

Cóż, miałem wielki problem z odgadnięciem komend nieblokujących... W końcu udało mi się przerobić przykład " Cookbook / Matplotlib / Animations-animowanie wybranych elementów wykresu ", więc działa z wątkami ( i przekazuje dane między wątkami albo poprzez zmienne globalne, albo przez wieloprocesor Pipe) na Pythonie 2.6.5 na Ubuntu 10.04.

Skrypt można znaleźć tutaj: Animating_selected_plot_elements-thread.py - inaczej wklejone poniżej ( z mniejszą komentarze ) dla odniesienia:

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! 

Mam nadzieję, że to komuś pomoże,
Zdrowie!

 6
Author: sdaau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-10 21:55:48

Jeśli pracujesz w konsoli, tj. IPython możesz użyć plt.show(block=False), Jak wskazano w innych odpowiedziach. Ale jeśli jesteś leniwy możesz po prostu wpisać:

plt.show(0)

Który będzie taki sam.

 5
Author: Anton Protopopov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-18 11:11:44

Ważne: żeby coś wyjaśnić. Zakładam, że polecenia znajdują się wewnątrz skryptu .py i skrypt jest wywoływany przy użyciu np. python script.py z konsoli.

Prosty sposób, który działa dla mnie to:

  1. użyj block = False Inside show: plt.show (block = False)
  2. użyj innego show () na końcu skryptu .py.

Przykład script.py Plik:

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

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

 5
Author: seralouk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-12 23:08:20

W wielu przypadkach jest to wygodniejsze do zapisania obrazu jako .plik png na dysku twardym. Oto dlaczego:

Zalety:

    Możesz go otworzyć, obejrzeć i zamknąć w każdej chwili. Jest to szczególnie wygodne, gdy aplikacja działa przez długi czas czas.
  • nic nie wyskakuje i nie musisz mieć otwartych okien. Jest to szczególnie wygodne, gdy masz do czynienia z wieloma postaciami.
  • Twój wizerunek jest dostępny do późniejszego wykorzystania i nie jest tracony podczas zamykania okna rysunku.

Wada:

  • jedyne, co przychodzi mi do głowy, to to, że będziesz musiał znaleźć folder i otworzyć obraz samodzielnie.
 4
Author: elgehelge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-18 18:21:54

Chciałem również, aby moje wykresy wyświetlały resztę kodu (a następnie wyświetlały), nawet jeśli wystąpi błąd (czasami używam Wykresów do debugowania). Zaszyfrowałem ten mały hacking, aby wszelkie wątki w tym with oświadczeniu zachowywały się tak samo.

Jest to prawdopodobnie zbyt niestandardowe i niewskazane dla kodu produkcyjnego. Prawdopodobnie w tym kodzie jest sporo ukrytych "gotchas".

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

If / when I implementing a proper " keep the plots open (even if an error is) and Zezwalaj na wyświetlanie nowych wykresów", chciałbym, aby skrypt poprawnie zakończył działanie, jeśli żadna ingerencja użytkownika nie mówi inaczej(dla celów wykonywania wsadowego).

Mogę użyć czegoś takiego jak przerwa-pytanie " koniec skryptu! \nPress p Jeśli chcesz, aby wynik wykresu został wstrzymany (masz 5 sekund): "od https://stackoverflow.com/questions/26704840/corner-cases-for-my-wait-for-user-input-interruption-implementation.

 3
Author: Simon Streicher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:32

W moim systemie show () nie blokuje, chociaż chciałem, aby skrypt czekał na interakcję użytkownika z grafem (i zbierał dane za pomocą wywołań zwrotnych' pick_event') przed kontynuowaniem.

Aby zablokować wykonanie do czasu zamknięcia okna wykresu, użyłem następującego:

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

Zwróć jednak uwagę, że płótno.start_event_loop_default () wygenerowało następujące ostrzeżenie:

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)

Chociaż skrypt nadal działał.

 2
Author: Andrew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-17 05:06:56

Musiałem również dodać plt.pause(0.001) do mojego kodu, aby naprawdę działał wewnątrz pętli for (w przeciwnym razie pokazywałby tylko pierwszy i ostatni Wykres):

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)
 2
Author: Martin Pecka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-09 14:16:16
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
 2
Author: thanhtang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-06 14:49:02

Moim zdaniem odpowiedzi w tym wątku dostarczają metod, które nie działają na każdym systemie i w bardziej złożonych sytuacjach, takich jak animacje. Proponuję rzucić okiem na odpowiedź MikeTex w poniższym wątku, gdzie znaleziono solidną metodę: Jak poczekać do zakończenia animacji matplotlib?

 1
Author: MikeTeX,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:24

Jeśli dobrze rozumiem pytanie, używając Ipython (lub IPython QT lub IPython notebook) pozwala na interaktywną pracę z wykresem, podczas gdy obliczenia idą w tle. http://ipython.org/

 0
Author: chrisfs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-24 04:18:42

Jeśli chcesz otworzyć wiele figur, zachowując je wszystkie otwarte, ten kod zadziałał dla mnie:

show(block=False)
draw()
 0
Author: DomDev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-16 15:11:08

Oto aktualizacja (python 3.6.5 na Windows 10).

Próbowałem różnych kombinacji-najprostszą, jaką znalazłem, jest użycie pause(0.01) po każdym wykresie - nie ma potrzeby stosowania show() dla pośrednich Wykresów - wtedy pojedynczy show() na końcu zapewnia, że możesz spojrzeć na końcowy wykres przed zakończeniem.

Jako przykład, oto fragment kodu, którego używam do sprawdzania prędkości dla różnych rozmiarów tablic - wyższe wartości wykresu to wyższe prędkości... istnieje 10 nakładanych działek...

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()
 0
Author: marzetti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-27 01:47:58