diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index fd78e6f94f19..3adc0710665d 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -1105,6 +1105,10 @@ def use(backend, *, force=True): """ Select the backend used for rendering and GUI integration. + If pyplot is already imported, `~matplotlib.pyplot.switch_backend` is used + and if the new backend is different than the current backend, all Figures + will be closed. + Parameters ---------- backend : str @@ -1135,6 +1139,8 @@ def use(backend, *, force=True): -------- :ref:`backends` matplotlib.get_backend + matplotlib.pyplot.switch_backend + """ name = validate_backend(backend) # don't (prematurely) resolve the "auto" backend setting diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index f11d66844a4c..ddde6c015133 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -209,21 +209,24 @@ def _get_backend_mod(): def switch_backend(newbackend): """ - Close all open figures and set the Matplotlib backend. + Set the pyplot backend. - The argument is case-insensitive. Switching to an interactive backend is - possible only if no event loop for another interactive backend has started. - Switching to and from non-interactive backends is always possible. + Switching to an interactive backend is possible only if no event loop for + another interactive backend has started. Switching to and from + non-interactive backends is always possible. + + If the new backend is different than the current backend then all open + Figures will be closed via ``plt.close('all')``. Parameters ---------- newbackend : str - The name of the backend to use. + The case-insensitive name of the backend to use. + """ global _backend_mod # make sure the init is pulled up so we can assign to it later import matplotlib.backends - close("all") if newbackend is rcsetup._auto_backend_sentinel: current_framework = cbook._get_running_interactive_framework() @@ -260,6 +263,8 @@ def switch_backend(newbackend): switch_backend("agg") rcParamsOrig["backend"] = "agg" return + # have to escape the switch on access logic + old_backend = dict.__getitem__(rcParams, 'backend') backend_mod = importlib.import_module( cbook._backend_module_name(newbackend)) @@ -323,6 +328,8 @@ def draw_if_interactive(): # Need to keep a global reference to the backend for compatibility reasons. # See https://github.com/matplotlib/matplotlib/issues/6092 matplotlib.backends.backend = newbackend + if not cbook._str_equal(old_backend, newbackend): + close("all") # make sure the repl display hook is installed in case we become # interactive diff --git a/lib/matplotlib/tests/test_pyplot.py b/lib/matplotlib/tests/test_pyplot.py index 2e51af54ea88..e6d17e42e93e 100644 --- a/lib/matplotlib/tests/test_pyplot.py +++ b/lib/matplotlib/tests/test_pyplot.py @@ -398,3 +398,14 @@ def test_minor_ticks(): tick_labels = ax.get_yticklabels(minor=True) assert np.all(tick_pos == np.array([3.5, 6.5])) assert [l.get_text() for l in tick_labels] == ['a', 'b'] + + +def test_switch_backend_no_close(): + plt.switch_backend('agg') + fig = plt.figure() + fig = plt.figure() + assert len(plt.get_fignums()) == 2 + plt.switch_backend('agg') + assert len(plt.get_fignums()) == 2 + plt.switch_backend('svg') + assert len(plt.get_fignums()) == 0