Skip to content

ENH: allow matplotlib.use after getbackend - #12608

Merged
tacaswell merged 3 commits into
matplotlib:masterfrom
jklymak:enh-change-backend
Oct 29, 2018
Merged

tacaswell merged 3 commits into
matplotlib:masterfrom
jklymak:enh-change-backend

Conversation

@jklymak

@jklymak jklymak commented Oct 24, 2018 •

Copy link
Copy Markdown
Member

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
Comment thread lib/matplotlib/__init__.py Outdated
force : bool, optional
If True, attempt to switch the backend. This defaults to
False.
True.

Copy link
Copy Markdown
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.

@anntzer anntzer left a comment

Copy link
Copy Markdown
Contributor

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



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

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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

jklymak commented Oct 24, 2018

Copy link
Copy Markdown
Member Author

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

jklymak commented Oct 24, 2018 •

Copy link
Copy Markdown
Member Author

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

anntzer commented Oct 24, 2018 •

Copy link
Copy Markdown
Contributor

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

jklymak commented Oct 24, 2018

Copy link
Copy Markdown
Member Author

@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
Copy Markdown
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

jklymak commented Oct 25, 2018

Copy link
Copy Markdown
Member Author

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
Copy Markdown
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
Copy Markdown
Member

but we will deal with that when it happens.

@anntzer

anntzer commented Nov 1, 2018

Copy link
Copy Markdown
Contributor

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