From 8ce25d1221697c3f2ccf4e94f7cd2bc0d692c3a6 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Tue, 18 Oct 2016 14:32:51 -0700 Subject: [PATCH] Traceback to help fixing double-calls to mpl.use. Example session: $ python -c 'import matplotlib as mpl; mpl.use("agg"); import matplotlib.pyplot; mpl.use("qt5agg")' -c:1: UserWarning: This call to matplotlib.use() has no effect because the backend has already been chosen; matplotlib.use() must be called *before* pylab, matplotlib.pyplot, or matplotlib.backends is imported for the first time. The backend was *originally* set to 'agg' by the following code: File "", line 1, in File "/home/antony/src/extern/matplotlib/lib/matplotlib/pyplot.py", line 68, in from matplotlib.backends import pylab_setup File "/home/antony/src/extern/matplotlib/lib/matplotlib/backends/__init__.py", line 14, in line for line in traceback.format_stack() (In practice, you'd expect the two calls to be further apart from each other, of course.) Note that the *current* traceback can be accessed by standard means, e.g. by setting the warnings filter. Not sure how easy this is to test. --- lib/matplotlib/__init__.py | 16 ++++++++++++---- lib/matplotlib/backends/__init__.py | 5 +++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index a1dd5adbef34..5df9bd58fdb8 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -1341,10 +1341,13 @@ def rc_file_defaults(): """ rcParams.update(rcParamsOrig) -_use_error_msg = """ This call to matplotlib.use() has no effect -because the backend has already been chosen; -matplotlib.use() must be called *before* pylab, matplotlib.pyplot, +_use_error_msg = """ +This call to matplotlib.use() has no effect because the backend has already +been chosen; matplotlib.use() must be called *before* pylab, matplotlib.pyplot, or matplotlib.backends is imported for the first time. + +The backend was *originally* set to {backend!r} by the following code: +{tb} """ @@ -1385,7 +1388,12 @@ def use(arg, warn=True, force=False): if 'matplotlib.backends' in sys.modules: # Warn only if called with a different name if (rcParams['backend'] != name) and warn: - warnings.warn(_use_error_msg, stacklevel=2) + import matplotlib.backends + warnings.warn( + _use_error_msg.format( + backend=rcParams['backend'], + tb=matplotlib.backends._backend_loading_tb), + stacklevel=2) # Unless we've been told to force it, just return if not force: diff --git a/lib/matplotlib/backends/__init__.py b/lib/matplotlib/backends/__init__.py index 68c3a91b1c59..c2b29d474d8d 100644 --- a/lib/matplotlib/backends/__init__.py +++ b/lib/matplotlib/backends/__init__.py @@ -5,10 +5,15 @@ import matplotlib import inspect +import traceback import warnings backend = matplotlib.get_backend() +_backend_loading_tb = "".join( + line for line in traceback.format_stack() + # Filter out line noise from importlib line. + if not line.startswith(' File "