Should plt.show() maybe do a plt.close() in all cases?

I have some .py’s that run either with a display or headless, generating frames of an animated gif. In one of those scripts, there was a plt.show() but not plt.close(). As a result, the headless runs aggregated all the prior plots into each subsequent frame, because in a headless environment I guess plt.show() is a NOOP whereas when a display is involved it ends up doing the equivalent of a plt.close().

I can gather more information if necessary. However, I don’t have access to the specific display environment at the moment and this issue seems easy enough to consider as described above.

Is this desirable/expected behavior or should I open a bug or feature request? It may be reasonable to expect that in headless environments, plt.show() should still have the same side-effects as in heads-up environments?

Depending on if you are in interactive mode or not, plt.show() will block the process until you close the figure (see https://matplotlib.org/users/interactive.html#interactive-mode).

If you are using plt.plot, plt.scatter, … you are implicitly plotting to “the current Axes” which is global state that pyplot is tracking. This can be very handy when working at an interactive prompt + GUI as it is nicely terse, but you are then responsible for keeping track of what “the current axes” is (as it changes when you click on the windows etc).

When you do plt.show(block=True) (either explicitly or implicitly via being in plt.ioff() mode) the Python process is blocked from continuing until you exit the gui event loop, typically by closing all of the open windows which in turn results in there being no open figures so the next plt.plot implicitly creates a new figure + axes.

When you do plt.show(block=False) (either explicitly or implicitly via being in plt.ion() mode) we just make sure the windows are “shown” and immediately return.

When we return from plt.show we don’t know why we returned and what the user is trying to do. In your case it sounds like doing an implicit plt.close('all') would be marginally better, it would likely break other users and make the closing of all figures dependent on the block mode which seems like it would cause more confusion in the long run!


If you are doing animation I suggest looking at https://matplotlib.org/api/animation_api.html#module-matplotlib.animation and prefer to update existing Artists rather than make new ones.

The usecase is not “exactly” an animation – as in morphing specific artists. Each frame shows a progressive analytical result, so various/many artists may change between frames, and it is easier to just redraw the plot. That said, thank you for linking that resource.

As an FYI, I gathered a bit more info about the heads-up context: It’s pycharm and plt.isinteractive reports False. I don’t have an installation of that IDE immediately available to test it myself but the reported behavior is that it throws up a series of charts without requiring user input at each frame. I guess it’s doing something analogous to the “closing all of the open windows” you mention…

Pycharm ship a custom backend which has slightly different behavior than the ones we ship.