Python Matplotlib: How to Clear and Close Matplotlib Figures in Python
Managing figure lifecycles in Matplotlib prevents memory leaks and ensures your plots render correctly. Understanding the difference between cla(), clf(), and close() is essential when creating multiple visualizations, especially in loops or long-running applications.
Understanding the Matplotlib Hierarchy
Matplotlib organizes visual elements in a three-level hierarchy, and each clearing method operates at a different level:
Figure (the window/canvas)
└── Axes (individual subplot)
└── Artists (lines, text, patches)
| Method | Target Level | What It Does |
|---|---|---|
cla() | Axes | Clears single subplot, preserves figure structure |
clf() | Figure | Removes all subplots, keeps window open |
close() | System | Destroys figure completely, releases memory |
Using cla() to Clear a Single Subplot
The cla() method clears the current axes (subplot) while maintaining the figure layout. This is useful for real-time updates or redrawing specific panels in a dashboard.
import matplotlib.pyplot as plt
import numpy as np
# Create a figure with two subplots
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))
# Plot initial data
ax1.plot([1, 2, 3, 4], [1, 4, 2, 3], 'b-', label='Original')
ax1.set_title('Left Panel')
ax1.legend()
ax2.plot([1, 2, 3, 4], [3, 1, 4, 2], 'r-', label='Data')
ax2.set_title('Right Panel')
ax2.legend()
plt.tight_layout()
plt.savefig('before_cla.png')
# Clear only the left subplot
ax1.cla()
# Redraw with new data: ax2 remains unchanged
ax1.plot([1, 2, 3, 4], [4, 3, 2, 1], 'g--', label='New Data')
ax1.set_title('Refreshed Left Panel')
ax1.legend()
plt.savefig('after_cla.png')
plt.show()
After calling cla(), you need to reapply axis labels, titles, and legends since these are considered part of the axes content.
Real-Time Animation Example
import matplotlib.pyplot as plt
import numpy as np
import time
fig, ax = plt.subplots()
plt.ion() # Enable interactive mode
for frame in range(50):
ax.cla() # Clear previous frame
# Generate new data
x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(x + frame * 0.1)
ax.plot(x, y, 'b-')
ax.set_ylim(-1.5, 1.5)
ax.set_title(f'Frame {frame}')
plt.pause(0.05)
plt.ioff()
plt.show()
Using clf() to Reset the Entire Figure
The clf() method clears the entire figure, removing all subplots and content while keeping the figure window open. Use this when you want to completely redesign a figure's layout.
import matplotlib.pyplot as plt
import numpy as np
# Create initial plot
plt.figure(figsize=(8, 6))
plt.subplot(2, 2, 1)
plt.plot([1, 2, 3], [1, 2, 3])
plt.subplot(2, 2, 2)
plt.plot([1, 2, 3], [3, 2, 1])
plt.suptitle('Original Layout')
plt.savefig('before_clf.png')
# Clear everything and start fresh
plt.clf()
# Create completely different layout
plt.subplot(1, 1, 1) # Single plot instead of 2x2
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x), 'r-', linewidth=2)
plt.title('Fresh Start - New Layout')
plt.xlabel('X axis')
plt.ylabel('Y axis')
plt.savefig('after_clf.png')
plt.show()
Comparing cla() and clf()
import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(1, 2)
ax1.plot([1, 2, 3])
ax2.plot([3, 2, 1])
# Using cla(): clears ax1 only, ax2 and layout preserved
ax1.cla()
print(f"After cla(): Figure has {len(fig.axes)} axes")
# Using clf(): removes everything
plt.clf()
print(f"After clf(): Figure has {len(fig.axes)} axes")
Output:
After cla(): Figure has 2 axes
After clf(): Figure has 0 axes
Using close() to Release Memory
The close() function destroys a figure completely, releasing all associated memory. This is critical for batch processing and long-running scripts.
import matplotlib.pyplot as plt
import numpy as np
def generate_report_pages(data_list, output_dir):
"""Generate multiple plot files without memory leaks."""
for i, data in enumerate(data_list):
# Create a new figure for each page
fig, ax = plt.subplots(figsize=(8, 6))
ax.plot(data['x'], data['y'])
ax.set_title(data['title'])
ax.set_xlabel('X')
ax.set_ylabel('Y')
# Save to file
filepath = f"{output_dir}/page_{i:03d}.png"
plt.savefig(filepath, dpi=150, bbox_inches='tight')
# Critical: release memory
plt.close(fig)
print(f"Generated {len(data_list)} pages")
# Example usage
data_list = [
{'x': range(10), 'y': [i**2 for i in range(10)], 'title': f'Chart {n}'}
for n in range(100)
]
generate_report_pages(data_list, './output')
Without plt.close(), each iteration creates a new figure that remains in memory. Processing hundreds of plots without closing them can consume gigabytes of RAM and eventually crash your program.
Different Ways to Close Figures
import matplotlib.pyplot as plt
# Create multiple figures
fig1 = plt.figure(num='First')
fig2 = plt.figure(num='Second')
fig3 = plt.figure(num=3)
# Close by figure object
plt.close(fig1)
# Close by figure number or name
plt.close('Second')
plt.close(3)
# Close the current active figure
plt.figure()
plt.plot([1, 2, 3])
plt.close() # Closes the most recent figure
# Nuclear option: close everything
plt.figure()
plt.figure()
plt.figure()
print(f"Open figures: {plt.get_fignums()}")
plt.close('all')
print(f"After close('all'): {plt.get_fignums()}")
Output:
Open figures: [1, 2, 3]
After close('all'): []
Memory Management Best Practices
Batch Processing Template
import matplotlib.pyplot as plt
import numpy as np
def create_batch_plots(n_plots):
"""Safely generate multiple plots."""
for i in range(n_plots):
try:
fig, ax = plt.subplots()
# Your plotting code
x = np.random.randn(100)
ax.hist(x, bins=20)
ax.set_title(f'Distribution {i}')
plt.savefig(f'hist_{i:04d}.png')
finally:
# Always close, even if an error occurs
plt.close(fig)
create_batch_plots(50)
Using Context Manager Pattern
import matplotlib.pyplot as plt
from contextlib import contextmanager
@contextmanager
def managed_figure(*args, **kwargs):
"""Context manager for automatic figure cleanup."""
fig = plt.figure(*args, **kwargs)
try:
yield fig
finally:
plt.close(fig)
# Usage
for i in range(100):
with managed_figure(figsize=(8, 6)) as fig:
ax = fig.add_subplot(111)
ax.plot([1, 2, 3], [i, i*2, i*3])
plt.savefig(f'managed_{i:03d}.png')
# Figure automatically closed here
Quick Reference
| Scenario | Method | Example |
|---|---|---|
| Update single subplot | ax.cla() | Real-time sensor display |
| Reset figure layout | plt.clf() | Interactive dashboard refresh |
| Batch file generation | plt.close(fig) | Report generation scripts |
| End of script cleanup | plt.close('all') | Notebook cells, test teardown |
| Animation frames | ax.cla() | Live data visualization |
In Jupyter notebooks, figures display automatically and are usually garbage collected between cells. However, explicitly calling plt.close() is still recommended when generating many figures in a single cell.
Understanding when to use each method ensures your visualizations render correctly while keeping memory usage under control: this is especially important in production environments and data pipelines.