HOWTO · Matplotlib
Cómo guardar gráficos como imágenes sin mostrarlos en Matplotlib
Guarde una figura de Matplotlib sin abrir una ventana mediante un backend no interactivo, savefig() y el orden correcto: guardar y después cerrar.
En esta página
Para guardar un gráfico completo de Matplotlib como imagen sin abrir una ventana gráfica, omite show(), guarda la figura concreta con savefig() y ciérrala solo después de escribir el archivo. En entornos realmente sin interfaz gráfica, selecciona el backend no interactivo Agg antes de importar pyplot.
Guardar un gráfico de Matplotlib sin mostrarlo
Para guardar una figura completa de Matplotlib sin abrir una ventana gráfica, omita show(), llame a savefig() desde la figura concreta y ejecute close() solo después de escribir el archivo. En un servidor, un trabajo de CI, un contenedor u otro entorno que necesite explícitamente un backend sin interfaz gráfica, seleccione el backend estático Agg antes de importar matplotlib.pyplot.
El orden esencial es seleccionar el backend, crear la figura, guardarla y después cerrarla. Conservar la referencia al objeto Figure hace inequívoco el destino y evita depender de la figura que pyplot considere activa.
Seleccionar Agg de forma explícita resulta útil cuando el script debe comportarse siempre igual en una máquina sin servidor de pantalla. No es necesario hacerlo solo porque guarde un archivo: Matplotlib puede elegir automáticamente un backend no interactivo adecuado. Si el comando no se puede modificar, también puede usar MPLBACKEND=Agg. No combine varios métodos de selección sin motivo, porque Matplotlib aplica un orden de precedencia y prevalece la última configuración aplicable.
Guardar una figura con el backend sin interfaz gráfica Agg
El siguiente ejemplo probado guarda un gráfico de una onda sinusoidal como sine-wave.png sin llamar a show(). Agg es un backend no interactivo que genera una salida ráster, por lo que no necesita una ventana en pantalla.
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)
La salida verificada es:
backend: Agg
saved: sine-wave.png
valid PNG: True
La imagen se escribe en una ruta relativa al directorio de trabajo actual del proceso. Es más seguro usar un Path absoluto o una ruta creada a partir de un directorio conocido del proyecto cuando un planificador o servicio pueda iniciar el script desde otra ubicación.
Las aserciones vuelven a abrir el PNG generado y confirman que existe y contiene datos de imagen. Esta comprobación detecta una salida ausente o ilegible, mientras que la vista previa confirma la curva, las etiquetas y la cuadrícula esperadas. En producción, elija una verificación igual de concreta cuando una exportación vacía o guardada en un lugar incorrecto pueda resultar costosa.
Elegir el formato de imagen y las opciones de savefig()
Por lo general, Figure.savefig() deduce el formato a partir de la extensión. Use PNG para una salida ráster ampliamente compatible, SVG para gráficos web escalables y PDF para un documento vectorial. Si el nombre no tiene una extensión adecuada, indique format de forma explícita.
En archivos ráster, dpi controla la resolución de salida; no hace más nítidos los trazos vectoriales de SVG o PDF. bbox_inches="tight" recorta el espacio sobrante, mientras que transparent=True vuelve transparentes los fondos de la figura y los ejes, salvo que sus colores se hayan sobrescrito. Estas opciones afectan al archivo exportado, no a la aparición de una ventana. Los formatos disponibles pueden depender del backend instalado y de bibliotecas opcionales.
Elija el formato según su destino. PNG es apropiado para un gráfico en un documento o página web; SVG mantiene nítidos los trazos y el texto cuando el navegador cambia su escala; PDF es práctico para impresión. Un valor alto de dpi aumenta las dimensiones ráster y el tamaño del archivo, por lo que conviene elegirlo según los requisitos reales.
Entender ioff(), show() y el orden de guardado
plt.ioff() desactiva el modo interactivo de pyplot, pero no es un interruptor universal para ejecutar Matplotlib sin interfaz gráfica. Las interfaces de los cuadernos pueden mostrar automáticamente la última figura de una celda aunque el modo interactivo esté desactivado. Use Agg cuando necesite un renderizador sin GUI y, en un cuaderno, suprima también el valor final de la figura o ciérrela después de guardarla.
Por otra parte, savefig() no necesita el modo interactivo ni show(). show() presenta figuras mediante un backend interactivo; omitirlo es habitual en un script dedicado únicamente a exportar. Desactivar la interacción y seleccionar un backend que genere archivos resuelven problemas relacionados, pero distintos.
Guarde antes de llamar a close(fig). Si cierra primero, pyplot elimina su referencia a esa figura, de modo que un plt.savefig() posterior y basado en estado puede actuar sobre otra figura o sobre una recién creada. La documentación de show() también advierte que guardar después de un show() bloqueante puede generar una figura vacía. Guarde primero o conserve el objeto de la figura y llame a su método savefig().
Liberar figuras en bucles y guardar en memoria
Pyplot conserva referencias a las figuras creadas mediante su interfaz. Un trabajo por lotes que cree muchos gráficos debe llamar a close(fig) después de guardar cada uno para poder liberar la figura y su memoria. Use un patrón try/finally cuando un procesamiento posterior pueda fallar.
Si otra API necesita los bytes de la imagen y no hace falta un archivo en disco, pase un objeto io.BytesIO a fig.savefig() en lugar de una ruta. Rebobine el búfer con seek(0) antes de leerlo o subirlo, y cierre igualmente la figura después de guardarla.
Gestionar un directorio de salida inexistente
savefig() crea el archivo de imagen, pero no los directorios superiores que falten. Este ejemplo de límite verificado captura el error y cierra la figura en todos los casos:
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().
Para una exportación real, cree antes el directorio con output.parent.mkdir(parents=True, exist_ok=True). Compruebe también que el proceso tenga permiso para escribir en él.
Usar imsave() con un array numérico
Use matplotlib.pyplot.imsave() cuando la entrada sea un array numérico 2D o RGB(A), en lugar de una figura trazada con ejes, etiquetas, leyendas y otros elementos. La función asigna los valores del array a píxeles de imagen y no sustituye a Figure.savefig() para guardar un gráfico 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