Warning for too many open shapes

In the script where I create many digits with fix, ax = plt.subplots(...) , I get a RuntimeWarning warning: more than 20 digits are open. Digits created through the pyplot interface ( matplotlib.pyplot.figure ) are stored until explicitly closed and may consume too much memory.

However, I don’t understand why I got this warning, because after saving the figure with fig.savefig(...) I delete it with fig.clear(); del fig fig.clear(); del fig . In no case in my code was there a single figure open at the same time. However, I get a warning about too many open shapes. What does it mean / how can I avoid the warning?

+117
python matplotlib
Feb 19 '14 at 15:00
source share
3 answers

Use .clf or .cla on the .cla object instead of creating a new drawing. From @DavidZwicker

Assuming you imported pyplot as

 import matplotlib.pyplot as plt 

plt.cla() clears the axis , i.e. the current active axis in the current drawing. This leaves the other axles intact.

plt.clf() clears the entire current digit with all its axes, but leaves the open window such that it can be reused for other graphs.

plt.close() closes the window , which will be the current window, unless otherwise specified. plt.close('all') will close all open digits.

The reason del fig doesn't work is because the pyplot machine pyplot keeps a reference to the shape around (as it should be if it knows what the "current digit" is). This means that even if you delete your reflector on the figure, there is at least one live ref, so it will never be garbage collected.

Since I am responding to collective wisdom here for this answer, @JoeKington mentions in the comments that plt.close(fig) will delete the specific ( plt._pylab_helpers.Gcf ) and allow it to collect garbage.

+152
Feb 19 '14 at 15:04
source share

Here's a little more detail to go to Captured Answer . When I first read this answer, I skipped the instruction to call clf() instead of creating a new shape. clf() alone does not help if you then go and create another shape.

Here is a trivial example that triggers a warning:

 from matplotlib import pyplot as plt, patches import os def main(): path = 'figures' for i in range(21): _fig, ax = plt.subplots() x = range(3*i) y = [n*n for n in x] ax.add_patch(patches.Rectangle(xy=(i, 1), width=i, height=10)) plt.step(x, y, linewidth=2, where='mid') figname = 'fig_{}.png'.format(i) dest = os.path.join(path, figname) plt.savefig(dest) # write image to file plt.clf() print('Done.') main() 

To avoid a warning, I have to get the subplots() call out of the loop. To see the rectangles, I need to switch clf() to cla() . This clears the axis without removing the axis itself.

 from matplotlib import pyplot as plt, patches import os def main(): path = 'figures' _fig, ax = plt.subplots() for i in range(21): x = range(3*i) y = [n*n for n in x] ax.add_patch(patches.Rectangle(xy=(i, 1), width=i, height=10)) plt.step(x, y, linewidth=2, where='mid') figname = 'fig_{}.png'.format(i) dest = os.path.join(path, figname) plt.savefig(dest) # write image to file plt.cla() print('Done.') main() 

If you generate graphics in batches, you may have to use both cla() and close() . I ran into a problem when a party could have more than 20 stories without complaining, but it would complain after 20 parties. I fixed this using cla() after each plot and close() after each batch.

 from matplotlib import pyplot as plt, patches import os def main(): for i in range(21): print('Batch {}'.format(i)) make_plots('figures') print('Done.') def make_plots(path): fig, ax = plt.subplots() for i in range(21): x = range(3 * i) y = [n * n for n in x] ax.add_patch(patches.Rectangle(xy=(i, 1), width=i, height=10)) plt.step(x, y, linewidth=2, where='mid') figname = 'fig_{}.png'.format(i) dest = os.path.join(path, figname) plt.savefig(dest) # write image to file plt.cla() plt.close(fig) main() 

I measured performance to see if it was worth reusing the shape in the package, and this small sample program slowed down from 41 to 49 seconds (20% slower) when I just called close() after each plot.

+21
May 20 '16 at 12:11
source share

If you intend to consciously store many graphs in memory, but do not want to be warned about this, you can update your parameters before creating the numbers.

 import matplotlib.pyplot as plt plt.rcParams.update({'figure.max_open_warning': 0}) 

This will prevent the warning from being issued without any changes to the way memory is managed.

+11
May 01 '18 at 18:50
source share



All Articles