30
votes

It seems that the standard way of creating a figure in matplotlib doesn't behave as I'd expect in python: by default calling fig = matplotlib.figure() in a loop will hold on to all the figures created, and eventually run out of memory.

There are quite a few posts which deal with workarounds, but requiring explicit calls to matplotlib.pyplot.close(fig) seems a bit hackish. What I'd like is a simple way to make fig reference counted, so I won't have to worry about memory leaks. Is there some way to do this?

2
It's really more like manual memory management, in this case, the figure is an external resource (like a file descriptor) to the Windowing system, and plt.figure() is the constructor, while plt.close(fig) is the destructor. Although there are many levels of destruction due to clf and cla and others. In this case, the proper way to do this would be to use the with bracketing idiom ("context manager"). - CMCDragonkai

2 Answers

33
votes

If you create the figure without using plt.figure, then it should be reference counted as you expect. For example (This is using the non-interactive Agg backend, as well.)

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

If you're only going to be saving figures rather than displaying them, you can use:

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

This is arguably no less hacky, but whatever.