HOWTO · Matplotlib
Salvare un grafico come immagine senza visualizzarlo in Matplotlib
Salva una figura Matplotlib senza aprire finestre usando un backend non interattivo, savefig() e il corretto ordine salvataggio-chiusura.
In questa pagina
Per salvare un grafico Matplotlib completo come immagine senza aprire una finestra grafica, ometti show(), salva la figura specifica con savefig() e chiudila solo dopo aver scritto il file. In ambienti realmente privi di interfaccia grafica, seleziona il backend non interattivo Agg prima di importare pyplot.
Salvare un grafico Matplotlib senza visualizzarlo
Per salvare una figura Matplotlib completa senza aprire una finestra grafica, non chiamare show(), usa savefig() sulla figura specifica e chiama close() solo dopo che il file è stato scritto. Su un server, in un processo CI, in un container o in un altro ambiente che richiede esplicitamente un backend headless, seleziona il backend statico Agg prima di importare matplotlib.pyplot.
L’ordine essenziale è selezionare il backend, costruire la figura, salvarla e infine chiuderla. Conservare il riferimento alla Figure rende inequivocabile la destinazione ed evita di dipendere dalla figura che pyplot considera attiva.
La selezione esplicita di Agg è utile quando lo script deve funzionare su un computer privo di display server. Non è necessaria solo perché uno script salva un file: Matplotlib può già scegliere automaticamente un backend non interattivo adatto. Per un comando non modificabile, si può usare MPLBACKEND=Agg. Non combinare più metodi di selezione senza motivo, perché prevale l’ultima configurazione applicabile.
Salvare una figura con il backend headless Agg
L’esempio verificato seguente salva un grafico sinusoidale in sine-wave.png senza chiamare show(). Agg è un backend non interattivo che produce output raster e non richiede una finestra sullo schermo.
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
output = Path("sine-wave.png")
x = np.linspace(0, 2 * np.pi, 200)
fig, ax = plt.subplots(figsize=(6, 4))
ax.plot(x, np.sin(x), color="#2166ac", linewidth=2)
ax.set(title="Sine wave", xlabel="x", ylabel="sin(x)")
ax.grid(alpha=0.25)
fig.savefig(output, dpi=150, bbox_inches="tight")
plt.close(fig)
saved = plt.imread(output)
assert output.is_file() and saved.size > 0
print("backend:", matplotlib.get_backend())
print("saved:", output.name)
print("valid PNG:", True)
L’output verificato è:
backend: Agg
saved: sine-wave.png
valid PNG: True
L’immagine viene scritta relativamente alla directory di lavoro corrente del processo. Un Path assoluto o costruito da una directory nota del progetto è più sicuro se uno scheduler o un servizio può avviare lo script altrove.
Le asserzioni riaprono il PNG generato e verificano che esista e contenga dati. Questo rileva un output assente o illeggibile, mentre l’anteprima conferma curva, etichette e griglia. In produzione, scegli una verifica altrettanto concreta se un’esportazione vuota o salvata nel posto sbagliato sarebbe costosa.
Scegliere il formato dell’immagine e le opzioni di savefig()
Figure.savefig() normalmente deduce il formato dall’estensione. Usa PNG per un raster ampiamente supportato, SVG per grafica web scalabile e PDF per un documento vettoriale. Se il nome non ha un’estensione adatta, passa esplicitamente format.
Per i raster, dpi controlla la risoluzione; non rende più nitidi i tracciati vettoriali in SVG o PDF. bbox_inches="tight" riduce lo spazio circostante, mentre transparent=True rende trasparenti gli sfondi, salvo colori impostati diversamente. Queste opzioni modificano il file esportato, non determinano se appare una finestra. I formati disponibili possono dipendere dal backend e dalle librerie opzionali.
Scegli il formato in base all’uso: PNG per documenti e pagine web, SVG per linee e testo ridimensionabili, PDF per la stampa. Un dpi elevato aumenta dimensioni raster e peso del file, quindi impostalo in base alle esigenze reali.
Capire ioff(), show() e l’ordine di salvataggio
plt.ioff() disabilita la modalità interattiva di pyplot, ma non è un interruttore headless universale. I frontend dei notebook possono mostrare automaticamente l’ultima figura di una cella anche con la modalità interattiva disattivata. Usa Agg quando serve un renderer senza GUI e sopprimi il valore finale nel notebook oppure chiudi la figura dopo il salvataggio.
Chiamare savefig() non richiede la modalità interattiva né show(). show() presenta le figure tramite un backend interattivo; ometterlo è normale in uno script di sola esportazione. Disattivare l’interazione e scegliere un backend che scrive file risolvono quindi problemi collegati ma diversi.
Salva prima di chiamare close(fig). Chiudere prima rimuove da pyplot il riferimento alla figura, quindi una successiva chiamata stateful a plt.savefig() può agire su una figura diversa o appena creata. Anche la documentazione di show() avverte che salvare dopo un show() bloccante può produrre una figura vuota: salva prima oppure conserva l’oggetto e chiama il suo metodo savefig().
Liberare le figure nei cicli e salvare in memoria
Pyplot conserva riferimenti alle figure create tramite la sua interfaccia. Un processo batch che genera molti grafici dovrebbe chiamare close(fig) dopo ogni salvataggio riuscito, così le figure e la memoria possono essere liberate. Usa try/finally quando un’elaborazione successiva potrebbe fallire.
Se un’altra API richiede i byte dell’immagine e non serve un file su disco, passa un oggetto io.BytesIO a fig.savefig(). Riporta il buffer all’inizio con seek(0) prima di leggerlo o caricarlo e chiudi comunque la figura dopo il salvataggio.
Gestire una directory di output mancante
savefig() crea il file immagine, ma non le directory genitrici mancanti. Questo esempio limite verificato intercetta l’errore e chiude la figura in ogni caso:
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
output = Path("missing") / "plot.png"
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [2, 4, 3])
try:
fig.savefig(output)
except FileNotFoundError:
print("Create the parent directory before savefig().")
finally:
plt.close(fig)
Create the parent directory before savefig().
Per un’esportazione reale, crea prima la directory con output.parent.mkdir(parents=True, exist_ok=True). Verifica inoltre che il processo abbia i permessi di scrittura.
Usare imsave() per un array numerico
Usa matplotlib.pyplot.imsave() quando l’input è un array numerico 2D o RGB(A), anziché una figura completa di assi, etichette, legende e altri artist. Il metodo associa i valori ai pixel e non sostituisce Figure.savefig() per un grafico completo.
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
pixels = np.array([[0.0, 0.5, 1.0], [1.0, 0.5, 0.0]])
output = Path("array-image.png")
plt.imsave(output, pixels, cmap="gray", vmin=0, vmax=1)
saved = plt.imread(output)
assert output.is_file() and saved.shape[:2] == pixels.shape
print("saved array:", output.name)
print("pixel grid:", saved.shape[0], "x", saved.shape[1])
saved array: array-image.png
pixel grid: 2 x 3