-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Description
Whilst looking at #14311 I discovered that in many circumstances we are unnecessarily calling matplotlib.pyplot.switch_backend twice when we only need to do so once.
Reproducer (using current main branches of ipython, matplotlib and matplotlib-inline):
$ ipython
<snip>
In [1]: import matplotlib.pyplot as plt; plt.set_loglevel("debug")
In [2]: %matplotlib tk
DEBUG:matplotlib.pyplot:Loaded backend qtagg version 5.15.9.
DEBUG:matplotlib.pyplot:Loaded backend TkAgg version 8.6.and in JupyterLab:
The cause is importing matplotlib_inline.backend_inline.configure_inline_support
ipython/IPython/core/interactiveshell.py
Line 3654 in 3d02f18
| from matplotlib_inline.backend_inline import configure_inline_support |
before calling
activate_matplotlibipython/IPython/core/interactiveshell.py
Line 3669 in 3d02f18
| pt.activate_matplotlib(backend) |
There is a side-effect of importing backend_inline which is to call _enable_matplotlib_integration:
https://github.com/ipython/matplotlib-inline/blob/0f419e31f2c3ab70d6bf0f1cd5950f993e01e360/matplotlib_inline/backend_inline.py#L228
which can call matplotlib.pyplot.switch_backend with the wrong backend before we call it with the correct one.
The solution is to move the import of backend_inline to after the correct activate_matplotlib(backend) call and before configure_inline_support is called. This works locally for me manually testing in Jupyter and IPython. I'll submit a PR with this to run the full CI suite on it.
An alternative would be to remove the import side-effect in matplotlib-inline and lazily call _enable_matplotlib_integration, but this will change more code and is potentially more dangerous as other libraries may be relying on the existing call.
I think this is a duplicate of (or overlaps with) #14006 and ipython/matplotlib-inline#25. There is a PR for latter that has a different solution but it has stalled, awaiting input from a Matplotlib maintainer. I am a (occasional) Matplotlib maintainer, and I prefer this solution as it doesn't poke around in the internals of either matplotlib or matplotlib-inline so is less risky.
