Gibt es eine Möglichkeit matplotlib Plots zu lösen, so dass die Berechnung fortgesetzt werden kann?

StackOverflow https://stackoverflow.com/questions/458209

  •  19-08-2019
  •  | 
  •  

Frage

Nach diesen Anweisungen in dem Python-Interpreter man ein Fenster mit einem Grundstück wird:

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

Leider weiß ich nicht, wie interaktiv weiterhin die Figur von show() erstellt erkunden, während das Programm weitere Berechnungen der Fall ist.

Ist es überhaupt möglich? Manchmal sind Berechnungen lang und es würde helfen, wenn sie bei der Untersuchung von Zwischenergebnissen gehen würden.

War es hilfreich?

Lösung

matplotlib die Anrufe verwenden, die nicht blockiert werden:

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

Mit dem interaktiven Modus:

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

Andere Tipps

Mit dem Schlüsselwort ‚Block‘ das Sperrverhalten außer Kraft zu setzen, z.B.

from matplotlib.pyplot import show, plot

plot(1)  
show(block=False)

# your code

Ihr Code, um fortzufahren.

Es ist besser, immer mit der Bibliothek überprüfen Sie verwenden, wenn es Nutzung unterstützt in einer nicht-blockierenden Art und Weise.

Wenn Sie aber eine allgemeinere Lösung wollen, oder wenn es keine andere Möglichkeit gibt, können Sie alles, was Blöcke in einem getrennten Prozess mit dem multprocessing Modul in python enthalten. Die Berechnung wird auch weiterhin:

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

Das ist der Aufwand bei der Einführung eines neuen Prozesses hat, und ist manchmal schwieriger, auf komplexe Szenarien zu debuggen, so würde ich die andere Lösung bevorzugen (matplotlib der nonblocking API-Aufrufe )

Versuchen

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.

Die show() Dokumentation sagt:

  

Im nicht-interaktiven Modus zeigen alle Figuren und Block, bis die Zahlen geschlossen wurden; im interaktiven Modus sie keinen Effekt hat, es sei denn Zahlen vor einer Änderung erstellt wurden, von nicht-interaktiven in den interaktiven Modus (nicht empfohlen). In diesem Fall zeigt es die Zahlen aber nicht blockiert.

     

Ein einziges experimentelles Schlüsselwort-Argument, block, eingestellt werden kann das Sperrverhalten der oben beschriebenen True oder False außer Kraft zu setzen.

Sie mögen dieses Dokument in matplotlib in der Dokumentation lesen, mit dem Titel:

Mit matplotlib in einem Python-Shell

Wichtig : Nur um etwas klar. Ich gehe davon aus, dass die Befehle in einem .py Skript und das Skript aufgerufen wird z.B. python script.py von der Konsole aus.

Eine einfache Art und Weise, die für mich funktioniert, ist:

  1. Verwenden Sie den Block = False innen zeigen: plt.show (Block = False)
  2. Mit einem anderen show () am Ende des Py-Skript.

Beispiel: script.py-Datei:

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

In meinem Fall wollte ich Pop-up mehr Fenster haben, wie sie berechnet werden. Als Referenz ist dies der richtige Weg:

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. Eine ganz nützlich führen OO-Schnittstelle matplotlib des .

Nun, ich große Mühe hatte, die nicht blockierende Befehle herauszufinden ... Aber schließlich gelang es mir, das zu überarbeiten „ Kochbuch / Matplotlib / Animationen Animieren Handlungselemente ausgewählt“, so funktioniert es mit Gewinden ( und übergibt Daten zwischen Threads entweder über globale Variablen oder durch einen Multi-Prozess-Pipe ) auf Python 2.6.5 auf Ubuntu 10.04.

Das Skript kann hier gefunden werden: Animating_selected_plot_elements-thread.py - sonst klebte unten ( mit weniger Kommentare ) Referenz:

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! 

Hope, das hilft jemand,
Cheers!

In vielen Fällen ist es bequeme til speichern Sie das Bild als .png-Datei auf der Festplatte. Hier ist der Grund:

Vorteile:

  • Sie können es öffnen, hat einen Blick auf sie und schließen Sie es jederzeit in dem Prozess nach unten. Dies ist besonders praktisch, wenn Ihre Anwendung für ein langen Lauf Zeit.
  • Nichts erscheint und Sie sind nicht die Fenster offen zu haben, gezwungen. Dies ist besonders praktisch, wenn Sie mit vielen Zahlen handeln.
  • Ihr Bild ist für den späteren Gebrauch auf zugänglich und nicht verloren geht, wenn die Figur Fenster schließen.

Nachteil:

  • Das einzige, was ich denken kann, ist, dass Sie den Ordner gehen und Finder müssen und öffnen Sie das Bild selbst.

Wenn Sie in der Konsole arbeiten, das heißt IPython Sie plt.show(block=False) verwenden könnte wie in den anderen Antworten darauf hingewiesen. Aber wenn Sie faul sind könnten Sie einfach ein:

plt.show(0)

, die die gleiche sein wird.

Ich musste auch plt.pause(0.001) zu meinem Code hinzufügen es wirklich für Schleife in einer Arbeits machen (sonst wäre es nur die erste und letzte Handlung zeigen):

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)

Ich wollte auch meine Plots den Rest des Codes ausgeführt werden angezeigt werden (und dann halten auf die Anzeige), selbst wenn ein Fehler aufgetreten ist (ich manchmal Plots für die Fehlersuche verwenden). Ich codierte diesen kleinen Hack, so dass alle Parzellen innerhalb dieser with Aussage als solche verhalten.

Dies ist wahrscheinlich ein bisschen zu Nicht-Standard und nicht für die Produktion Code ratsam. Es gibt wahrscheinlich viele versteckte „Fallstricke“ in diesem Code.

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

Wenn / wenn ich eine ordnungsgemäße Umsetzung „halten die Plots geöffnet (auch wenn ein Fehler auftritt) und ermöglichen neue Plots gezeigt werden“, würde ich das Skript wollen richtig beendet, wenn kein Benutzereingriff es anders erklärt (für Batch-Ausführung Zwecke).

Ich kann so etwas wie eine Time-out-Frage verwenden "End of script \ nDrücken p, wenn Sie das Plotten Ausgang anzuhalten (Sie haben 5 Sekunden) wollen:" von https://stackoverflow.com/questions/26704840/corner-cases-for-my-wait- for-user-input-Unterbrechung-Implementierung .

Auf meinem System show () nicht blockiert, obwohl ich das Drehbuch wollte für den Benutzer zu warten, mit dem Graphen zu interagieren (und sammeln Daten mit ‚pick_event‘ Rückrufen), bevor Sie fortfahren.

Um die Ausführung zu blockieren, bis die Handlung Fenster geschlossen ist, habe ich die folgenden:

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

Beachten Sie jedoch, dass canvas.start_event_loop_default () erzeugt die folgende Warnung:

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)

obwohl das Skript noch lief.

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

Meiner Meinung nach, die Antworten in diesem Thread Methoden bereitzustellen, die für alle Systeme nicht funktionieren und in komplexeren Situationen wie Animationen. Ich schlage vor, einen Blick auf die Antwort von MiKTeX in folgendem Thread zu haben, wo eine robuste Methode gefunden wurde: Wie warten, bis matplotlib Animation endet?

Wenn Sie mehrere Figuren öffnen möchten, während sie alle geöffnet zu halten, dieser Code arbeitete für mich:

show(block=False)
draw()

Die OP fragt nach matplotlib Plots detatching. Die meisten Antworten übernehmen Befehlsausführung aus einem Python-Interpreter. Die Use-Case präsentierte hier ist meine Vorliebe für die Code-Prüfung in einem Endgerät (zum Beispiel bash), wo ein file.py ausgeführt wird, und Sie wollen die Handlung (en) zu kommen, aber der Python-Skript zu beenden und zu einer Eingabeaufforderung zurückzukehren.

Diese eigenständige Datei verwendet multiprocessing einen separaten Prozess zu starten, um Daten mit matplotlib Plotten. Der Haupt-Thread verlässt den os._exit(1) in Diese Post. Die os._exit() Kräfte Haupt zu verlassen, sondern verlässt den matplotlib Kind Prozess lebendig und reaktionsschnell, bis das Grundstück Fenster geschlossen wird. Es ist ein separater Prozess vollständig.

Dieser Ansatz ist ein bisschen wie eine Matlab Entwicklung Sitzung mit Abbildung Fenstern, die mit einer ansprechenden Eingabeaufforderung kommen. Mit diesem Ansatz haben Sie jeden Kontakt mit der Figur Fenster verloren, aber das ist in Ordnung für die Entwicklung und das Debugging. schließen Sie einfach das Fenster und halten Tests.

multiprocessing ist für Python-only Codeausführung entwickelt, die es vielleicht besser geeignet als subprocess macht. multiprocessing ist Cross-Plattform, so sollte dies gut funktioniert in Windows oder Mac mit wenig oder gar keiner Anpassung. Es besteht keine Notwendigkeit, das zugrunde liegende Betriebssystem zu überprüfen. Dies wurde auf Linux getestet, 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

Beim Laufen file.py bringt eine Abbildung Fenster, dann __main__ Ausfahrten aber die multiprocessing + matplotlib Figur Fenster bleiben reaktions mit Zoom, Pan und anderen Tasten, weil es ein unabhängiger Prozess ist.

Überprüfen Sie die Prozesse an der Bash-Eingabeaufforderung mit:

ps ax|grep -v grep |grep file.py

Mit plt.show(block=False), und am Ende des Skriptes Anruf plt.show().

Dadurch wird sichergestellt, dass das Fenster nicht geschlossen werden, wenn das Skript beendet ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top