Skip to content

ENH: allow matplotlib.use after getbackend #12608

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

Merged
merged 3 commits into from
Oct 29, 2018

Conversation

jklymak
Copy link
Member

@jklymak jklymak commented Oct 24, 2018

PR Summary

Closes the long-desired ability to just call matplotlib.use so long as another GUI backend hasn't been started:

Closes #12362 (for example)

import matplotlib
import matplotlib.pyplot as plt

matplotlib.use('Qt5Agg')
print('backend:', matplotlib.get_backend())
if not matplotlib.get_backend() == 'MacOSX':
    matplotlib.use('MacOSX')
print('backend:', matplotlib.get_backend())

plt.plot(range(10))
plt.show()
matplotlib.use('Qt5Agg')

With this PR:

$ pythonw testgetbackend.py
backend: Qt5Agg
backend: MacOSX
Traceback (most recent call last):
  File "testgetbackend.py", line 11, in <module>
    matplotlib.use('Qt5Agg')
  File "/Users/jklymak/matplotlib/lib/matplotlib/__init__.py", line 1355, in use
    switch_backend(name)
  File "/Users/jklymak/matplotlib/lib/matplotlib/pyplot.py", line 222, in switch_backend
    newbackend, required_framework, current_framework))
ImportError: Cannot load backend 'Qt5Agg' which requires the 'qt5' interactive framework, as 'macosx' is currently running

Before:

$ pythonw testgetbackend.py
testgetbackend.py:3: UserWarning: matplotlib.pyplot as already been imported, this call will have no effect.
  matplotlib.use('Qt5Agg')
backend: MacOSX
backend: MacOSX
testgetbackend.py:11: UserWarning: matplotlib.pyplot as already been imported, this call will have no effect.
  matplotlib.use('Qt5Agg')

PR Checklist

  • Has Pytest style unit tests
  • Code is Flake 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

@jklymak jklymak requested review from anntzer, efiring and tacaswell and removed request for efiring October 24, 2018 02:32

force : bool, optional
If True, attempt to switch the backend. This defaults to
False.
True.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mention that this will raise ImportError on failure, which occurs if an incompatible event loop has already started.

Copy link
Contributor

@anntzer anntzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

except for minor doc improvement

@@ -1292,7 +1292,7 @@ def __exit__(self, exc_type, exc_value, exc_tb):
self.__fallback()


def use(arg, warn=True, force=False):
def use(arg, warn=False, force=True):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it's very remotely an API break in the sense that some previously invalid calls to use() would raise a warning and do nothing whereas they will now throw an exception, but I'm not sure if it's worth an API note :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API note added. As per below I wonder if we really want to stick closer to the original behaviour and trap the Error, warn, and not switch the backend.

@tacaswell tacaswell modified the milestones: v3.1, v3.0.x Oct 24, 2018
@tacaswell
Copy link
Member

This is the API change we decided not to make for 3.0.

I am still skeptical, but slowing coming around to this being the right path.

@jklymak
Copy link
Member Author

jklymak commented Oct 24, 2018

I thought the API discussion was about the role of rcParams in all this. But since that’s what we do now, changing that can wait.

Of course the way things are before this PR we could have been telling people to use Force=True

@jklymak
Copy link
Member Author

jklymak commented Oct 24, 2018

BTW, I'd also be fine w/

import matplotlib
import matplotlib.pyplot as plt

matplotlib.use('Qt5Agg')
plt.plot(range(10)); plt.show()
matplotlib.use('MacOSX')

warning and doing nothing, rather than throwing an ImportError. It'd be easy to trap the ImportError.

@anntzer
Copy link
Contributor

anntzer commented Oct 24, 2018

It's not as if it was particularly hard for the end user to catch the import error, and not everyone reads warnings (in the long term I'd like to get rid of force and warn, which are kind of silly now that backend switching works, but that's for another day...).

@jklymak
Copy link
Member Author

jklymak commented Oct 24, 2018

@anntzer, I agree, but that behaviour is not as key to me as the ability for matplotlib.use to actually change the backend before the GUI has started.

@tacaswell tacaswell modified the milestones: v3.0.1, v3.0.x Oct 25, 2018
@tacaswell
Copy link
Member

re-milestoned out of 3.0.1 as I want to think about this a bit more not under the pressure of "we need to get out a bug-fix-release that works on py3.7.1"

@jklymak
Copy link
Member Author

jklymak commented Oct 25, 2018

Just to get folks thinking about this, what are the cons of this change?

@tacaswell tacaswell merged commit 8c44c4d into matplotlib:master Oct 29, 2018
meeseeksmachine pushed a commit to meeseeksmachine/matplotlib that referenced this pull request Oct 29, 2018
jklymak added a commit that referenced this pull request Oct 29, 2018
…608-on-v3.0.x

Backport PR #12608 on branch v3.0.x (ENH: allow matplotlib.use after getbackend)
@jklymak jklymak deleted the enh-change-backend branch October 31, 2018 15:29
@tacaswell
Copy link
Member

On a bit more consideration, I suspect we are going to get a wave of "why are my figures not interactive?" bug reports that trace back to the GUI wrappers installing conflicting input hooks.

@tacaswell
Copy link
Member

but we will deal with that when it happens.

@anntzer
Copy link
Contributor

anntzer commented Nov 1, 2018

Again, hopefully input hooks are only installed when the event loop is started, not when the package is imported.
Otherwise we'll have to resort to stuff to get the metadata about a backend (i.e. its event loop) without importing it; it's a bit a pain but not impossible (put that in a text file next to it with the same name and use the import machinery to find it without doing the import...).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

In 3.0.0 backend cannot be set if 'get_backend()' is run first
3 participants