2013-05-02 25 views
17

Sembra che il modo standard di creare una figura in matplotlib non si comporti come mi aspetterei in python: per impostazione predefinita, la chiamata a fig = matplotlib.figure() in un ciclo resterà su tutte le figure create, e alla fine a corto di memoria.Creare una figura conteggiata

ci sono quiteafew i messaggi che si occupano di soluzioni alternative, ma che richiedono chiamate esplicite a matplotlib.pyplot.close(fig) sembra un po 'hacker. Quello che mi piacerebbe è un modo semplice per fare il conteggio di fig conteggiato, quindi non dovrò preoccuparmi di perdite di memoria. C'è un modo per farlo?

+1

È molto più simile alla gestione manuale della memoria, in questo caso la figura è una risorsa esterna (come un descrittore di file) al sistema Windowing, e 'plt.figure()' è il costruttore, mentre 'plt.close (fig) 'è il distruttore. Sebbene ci siano molti livelli di distruzione dovuti a 'clf' e' cla' e altri. In questo caso, il modo corretto per farlo sarebbe quello di usare l'idioma bracketing 'with' (" context manager "). – CMCDragonkai

risposta

18

Se si crea la figura senza utilizzare plt.figure, è necessario contare conteggio come previsto. Per esempio (. Si tratta di utilizzare il backend non interattivo Agg, come pure)

from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas 
from matplotlib.figure import Figure 

# The pylab figure manager will be bypassed in this instance. 
# This means that `fig` will be garbage collected as you'd expect. 
fig = Figure() 
canvas = FigureCanvas(fig) 
ax = fig.add_subplot(111) 
+2

Senza 'FigureCanvas (fig)' Ricevo un'eccezione quando provo a salvare la figura. Suppongo che un 'Figure' debba sempre essere disegnato con un' FigureCanvas'? – Shep

+2

Sì! Altrimenti non si può tracciare nulla (gli artisti sono creati, ma il disegno non avviene finché non si salva/mostra la trama). È una verruca nell'API; idealmente la tela sarebbe iniziata insieme alla figura. Potrebbe avere più senso se si usa 'canvas.print_figure (filename)' invece di 'fig.savefig (filename)' (che è in effetti ciò che 'fig.savefig' fa dietro le quinte). Questo è puramente per la tua comprensione, però (la tela è la parte specifica del back-end che gestisce il disegno/salvataggio). Il risultato finale è lo stesso. –

+1

Hmm, quindi la tela deve esistere prima di salvare? Mi chiedo se 'FigureCanvas (fig) .print_figure (filename)' funzioni come una funzione di stampa a una riga. – Shep

2

Se si sta solo andando a salvare i dati, piuttosto che la loro visualizzazione, è possibile utilizzare:

def savefig(*args, **kwargs): 
    plt.savefig(*args, **kwargs) 
    plt.close(plt.gcf()) 

Questo è probabilmente non meno hacky, ma qualunque cosa.

+0

Grazie, ma mentre questo mi dice come salvare una figura e chiuderla non risponde alla domanda-è un po 'come rispondere "come uso i puntatori intelligenti in C++" con "allocare un puntatore raw e poi chiamare' delete "quando hai finito". – Shep

+0

È giusto, suggerendo semplicemente una soluzione alternativa a "Come posso non preoccuparmi delle perdite di memoria" che utilizza ancora l'API standard di 'plt'. –

Problemi correlati