Skip to content

Commit b94f5c0

Browse files
committed
FIX: be more careful about not importing pyplot early
In matplotlib.use we import pyplot to use `switch_backend`, however if the user calls `mpl.use(...)` before importing pyplot then during the initial import of pyplot, before we set the selected backend we try to set the backend set via rcParams. This change only imports pyplot if it is already imported, otherwise it is safe to just set the rcParams and not go through the full `plt.switch_backend` path. closes #17763
1 parent 4a143b9 commit b94f5c0

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

lib/matplotlib/__init__.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,16 +1136,34 @@ def use(backend, *, force=True):
11361136
matplotlib.get_backend
11371137
"""
11381138
name = validate_backend(backend)
1139+
# we need to use the base-class method here to avoid (prematurely)
1140+
# resolving the "auto" backend setting
11391141
if dict.__getitem__(rcParams, 'backend') == name:
11401142
# Nothing to do if the requested backend is already set
11411143
pass
11421144
else:
1143-
try:
1144-
from matplotlib import pyplot as plt
1145-
plt.switch_backend(name)
1146-
except ImportError:
1147-
if force:
1148-
raise
1145+
# if pyplot is not already imported, do not import it. Doing
1146+
# so may trigger a `plt.switch_backend` to the _default_ backend
1147+
# before we get a chance to change to the one the user just requested
1148+
plt = sys.modules.get('matplotlib.pyplot')
1149+
# if pyplot is imported, then try to change backends
1150+
if plt is not None:
1151+
try:
1152+
# we need this import check here to re-raise if the
1153+
# user does not have the libraries to support their
1154+
# chosen backend installed.
1155+
plt.switch_backend(name)
1156+
except ImportError:
1157+
if force:
1158+
raise
1159+
# if we have not imported pyplot, then we can set the rcParam
1160+
# value which will be respected when the user finally imports
1161+
# pyplot
1162+
else:
1163+
rcParams['backend'] = backend
1164+
# if the user has asked for a given backend, do not helpfully
1165+
# fallback
1166+
rcParams['backend_fallback'] = False
11491167

11501168

11511169
if os.environ.get('MPLBACKEND'):

lib/matplotlib/tests/test_rcparams.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,10 @@ def test_backend_fallback_headless(tmpdir):
473473
with pytest.raises(subprocess.CalledProcessError):
474474
subprocess.run(
475475
[sys.executable, "-c",
476-
"import matplotlib; matplotlib.use('tkagg')"],
476+
("import matplotlib;" +
477+
"matplotlib.use('tkagg');" +
478+
"import matplotlib.pyplot")
479+
],
477480
env=env, check=True)
478481

479482

0 commit comments

Comments
 (0)