-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Backend switching #9795
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Backend switching #9795
Conversation
4fae022
to
33aa68c
Compare
This looks really cool. But, I'm on MacOS so its not working for me yet. If I do import matplotlib
print(matplotlib.get_backend())
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt
plt.scatter([1, 2], [0,2])
print(matplotlib.get_backend())
plt.show() I get a Qt5Agg GUI and
If I do import matplotlib
print(matplotlib.get_backend())
import matplotlib.pyplot as plt
matplotlib.use('Qt5Agg')
plt.scatter([1, 2], [0,2])
print(matplotlib.get_backend())
plt.show() I get:
but, I get the macOS GUI (Toolbar on the bottom instead of top, and I can close with command-w). So either I am not understanding how to test this or MacOS needs work. Happy to help make this work on MacOS... |
That's because I forgot to actually update the backend when doing Right now what needs to be done for OSX is a way to detect whether the OSX event loop is already running (see _get_current_event_loop for examples), so that having an OSX event loop running prevents starting another event loop. |
Confirmed, the snippet above now works as advertized! |
BTW, looking at event-loops and such would be a longer term project for me if I were to help. @dopplershift would probably be much better suited. |
9ff786e
to
c689eac
Compare
c689eac
to
307c1ec
Compare
307c1ec
to
6725bf4
Compare
8a08283
to
c745e17
Compare
f865c09
to
1083c3c
Compare
I just tried on your machine and it worked for me... Can you check what's happening at INFO log level, especially during the call to matplotlib.backends.pylab_setup? |
@anntzer is this still active? Sorry if I was supposed to get back to you on some of it - looks like it'll be an ugly rebase, but they are probably all your changes anyways 😉 |
I'll probably wait until the rest of the mpl3 transition settles down a bit before revisiting this. |
Some version of this should go in for 3.0 to make life easier for conda-forge. |
Frankly, I wouldn't say no to some progress on merging my 61 other currently open PRs rather than seeing them bitrot one after another like this one. |
This is the followup to #9551 (backend loading refactor), and includes it (so it would make sense for #9551 to be merged first).
This PR removes the ambiguous behavior of
matplotlib.use
, which was, up to now, documented as follows:Instead, matplotlib.use now works just fine as long as an event loop has not started yet (i.e. an interactive window popped up), or when switching to a noninteractive backend, or to an interactive backend compatible with the current event loop (e.g. gtk3agg -> gtk3cairo); in all other cases, an exception is raised. This means, for example, that one can write
from matplotlib import pyplot as plt; plt.rcParams["backend"] = "foo"; ...
instead of having to do a separate import of matplotlib.Moreover, it is now possible to set rcParams["backend"] to a list of candidate backends; they will simply be tested one at a time until one succeeds. If pyplot is already loaded, the value in rcParams["backend"] is immediately replaced by the successful candidate. If pyplot is not loaded yet, rcParams["backend"] will keep hold of the list of candidates until pyplot is loaded. This is a documented change of behavior (users should import pyplot to force backend resolution). (Alternatively the list could be shoved into a new, separate rcParam, but little would be gained because rcParams["backend"] would then hold an incorrect value until backend resolution). Another change of behavior is that the matplotlib.backends.backend global variable has been removed, again in favor of rcParams["backend"] as single truth point: it was too difficult to properly keep matplotlib.backends.backend in sync, especially at import time when that module may not have been imported yet.
(Exception: I don't have a Mac available to figure out the relevant fixes for the OSX backend, but hopefully another contributor can help here. See _get_current_event_loop.)
Edit: Now also working on OSX, see comment below.
A major advantage of such a scheme is that we can now just ship a default matplotlibrc which lists all buitin backends in preference order (
backend: osx, qt5agg, qt4agg, gtk3agg, ...
). Currently, this list is evaluated at build time (by testing which GUI toolkit is importable), which causes two major problems: 1) the import of the GUI toolkits need to happen in separate processes, which means that setup.py relies on multiprocessing(!); for example, this appears to confuse conda-build (see comment in ci/conda_recipe/meta.yaml); 2) the built list is useless anyways unless 1) the end user is doing the build, rather than a central packager (the end user may have a different list of installed GUI toolkits...) and 2) the end user never adds or removes a new GUI toolkit. Here, I can instead completely strip out the relevant part of setupext.py, greatly simplifying it.The backend_fallback rcParam likewise becomes obsolete, although this PR does not remove it (this rcParam can easily go through a normal deprecation route).
I also removed the interactive backends API docs because the shimming (to allow them to be imported in a headless buildbot) was insufficient to support this PR's implementation. Proposed fix at #9708 (comment). (But note that they were incomplete anyways...)
Closes #3679, #6739, #8613, #9017 (comment); sort-of #3466 (which is perhaps more a doc issue...).
Some comments to try clarifying the implementation:
use(...); rcdefaults()
working: this implies thatuse(...)
must overwrite the default backend (in rcParamsDefault, and likewise rcParamsOrig), to a single fixed value.