FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

[ENH]: Does pyplot need to call switch_backend · Issue #22739 · matplotlib/matplotlib · GitHub

Repository navigation

[ENH]: Does pyplot need to call switch_backend #22739

Closed

Description

Problem

It seems that simply importing pyplot can have serious effects on what backends are chosen, and how they interact with one and other.

In

# if pyplot is not already imported, do not import it. Doing

They say that simply

from matplotlib import pyplot

can trigger setting the default backend.

This is somewhat frustrating for people who use interactive sessions.

Running the code

from matplotlib import pyplot
import matplotlib
matplotlib.use("WxAgg")

all at once will work in ipython (from the terminal). But running it one line at a time, won't.

This is somewhat strange.

Now that things like __getattr__ exist, would be possible to further delay setting the default backend?

The issue arises when you want to build an application, and other people's code might be imported before yours. You are then at their mercy to not set the backend (implicitly!) before you set yours.

Proposed solution

No solution. I'm sure there is some strange historic thing I'm missing.

Honestly, you created a great API with pyplot. People use it to get colormaps, and for all sorts of things.

XREF: DeepLabCut/DeepLabCut#1730

Activity

  1. WeatherGod commented on Mar 31, 2022

    Member
  2. hmaarrfk commented on Mar 31, 2022

    ContributorAuthor

    ok, understood. I didn't know if patches would be welcome that would defer that.

    Is there an API that application developers can use that is independent of the chosen backend? That is, they would specify their own handles/backend name and matplotlib will forcibly use that?

  3. timhoffm commented on Mar 31, 2022

    Member

    Deferring backed selection has been implemented in #22005, but is not yet released.

    Is there an API that application developers can use that is independent of the chosen backend?

    I'm not the backend expert here, but I'm not aware of a reasonably simple way to do this.

    General question: Is there a reason that we need global exclusive backend state and cannot have a per-figure backend setting?

  4. jklymak commented on Mar 31, 2022

    Member

    General question: Is there a reason that we need global exclusive backend state and cannot have a per-figure backend setting?

    I don't know - is it really worth the trouble to allow multiple GUI backends to run at the same time? I could see us allowing one GUI to be closed and a different one opened after the GUI is closed, but I'm not sure its a good idea for one python process to have multiple GUI frameworks running at the same time?

    We probably should revisit the roadmap for https://github.com/matplotlib/mpl-gui

  5. hmaarrfk commented on Mar 31, 2022

    ContributorAuthor

    Well... I feel like it might be address in the next release.
    #22005

  6. hmaarrfk commented on Mar 31, 2022

    ContributorAuthor

    Can't wait!

  7. timhoffm commented on Mar 31, 2022

    Member

    @hmaarrfk does #22005 address your needs? If so we can close this issue.

  8. hmaarrfk commented on Mar 31, 2022

    ContributorAuthor

    I'm not entirely sure. It is kinda hard to compile matplotlib and backporting the patch wasn't super easy.

    There still seems to be eager code in:
    https://github.com/matplotlib/matplotlib/blob/main/lib/matplotlib/pyplot.py#L2246

    so i really wnat to have the time to test before saying it is fixed.

  9. hmaarrfk commented on Mar 31, 2022

    ContributorAuthor

    The comment I referred to in the init file seems suspicious now too.

  10. anntzer commented on Mar 31, 2022

    Contributor

    Is there a reason that we need global exclusive backend state and cannot have a per-figure backend setting?

    You cannot have e.g. both qt and tk running as they'll fight over https://docs.python.org/3/c-api/veryhigh.html#c.PyOS_InputHook. You could allow e.g. qtcairo + qtagg or any interactive backend + any noninteractive backend, but I'm not sure it's worth the engineering...

  11. timhoffm commented on Mar 31, 2022

    Member

    You cannot have e.g. both qt and tk running as they'll fight over https://docs.python.org/3/c-api/veryhigh.html#c.PyOS_InputHook.

    I can if I have different processes 😝

  12. tacaswell commented on Mar 31, 2022

    Member

    if (rcParams["backend_fallback"]
    and dict.__getitem__(rcParams, "backend") in (
    set(_interactive_bk) - {'WebAgg', 'nbAgg'})
    and cbook._get_running_interactive_framework()):
    dict.__setitem__(rcParams, "backend", rcsetup._auto_backend_sentinel)

    says:

    • if the user asked for fallback (meaning get a working gui not fail on the gui they asked for)
    • and the backend is one of ours that we know uses a GUI toolkit (but excluding the web backends)
    • and would that there is already a running event loop (but not starting an event loop)

    then set the backend to "automatic" and let the later machinery sort out detecting which one is running and doing the correct selection then.

  13. tacaswell commented on Mar 31, 2022

    Member

    # if pyplot is not already imported, do not import it. Doing
    # so may trigger a `plt.switch_backend` to the _default_ backend
    # before we get a chance to change to the one the user just requested
    plt = sys.modules.get('matplotlib.pyplot')
    # if pyplot is imported, then try to change backends
    if plt is not None:
    try:
    # we need this import check here to re-raise if the
    # user does not have the libraries to support their
    # chosen backend installed.
    plt.switch_backend(name)
    except ImportError:
    if force:
    raise
    # if we have not imported pyplot, then we can set the rcParam
    # value which will be respected when the user finally imports
    # pyplot
    else:
    rcParams['backend'] = backend

    This code is saying "if the user explicitly called mpl.use(...) then make sure right now that is something we can actually do. That comment needs to be adjusted now that #22005 is merged.

    I am morbidly curious why it was going wrong before but I do think it is fixed.

    I'm not entirely sure. It is kinda hard to compile matplotlib and backporting the patch wasn't super easy.

    Where are you trying to backport it to?

    If you can compile skimage, I would also expect Matplotlib to compile "out of the box" as well...

  14. tacaswell commented on Apr 1, 2022

    Member

    And thank to #22733 which just got merged

    python -m pip install --upgrade --index-url https://pypi.anaconda.org/scipy-wheels-nightly/simple matplotlib
    

    will now get you nightlies!

  15. ianhi commented on Apr 1, 2022

    Contributor

    Slight correction to that install command. To get everything to work properly with dependencies you need to run:

    python -m pip install --upgrade --pre --index-url https://pypi.anaconda.org/scipy-wheels-nightly/simple --extra-index-url https://pypi.org/simple matplotlib
    
  16. hmaarrfk commented on Apr 1, 2022

    ContributorAuthor

    If you can compile skimage, I would also expect Matplotlib to compile "out of the box" as well...

    Touchée .

    I guess I'm using conda for most environment management.
    It becomes a pain to remove matplotlib-core and replace it with matplotlib

    I'll give it a try in a few hours.

  17. WeatherGod commented on Apr 1, 2022

    Member

    Is there an API that application developers can use that is independent of the chosen backend? That is, they would specify their own handles/backend name and matplotlib will forcibly use that?

    You might be interested in my book, "Interactive Applications using Matplotlib". It is a little out of date now (published almost 7 years ago!), but many of the principles are still true. In it, it describes how to embed a figure as a widget in an existing GUI application. It also shows how to embed GUI widgets into a regular matplotlib figure window.

    Furthermore, it also talks about some of the GUI-agnostic widgets that are available so that you can have an application that'll work in just about any interactive environment.

  18. hmaarrfk commented on Apr 1, 2022

    ContributorAuthor

    I'm not going to say I can't get it to compile from source, but I am going to say that for my conda environment, I tried:

    conda uninstall --force --offline --yes matplotlib base
    pip install -e . -vv --no-deps
    

    and it resulted in:

    $ ipython
    Python 3.9.9 (main, Dec 29 2021, 07:47:36)
    Type 'copyright', 'credits' or 'license' for more information
    IPython 8.1.1 -- An enhanced Interactive Python. Type '?' for help.
    
    In [1]: from matplotlib import pyplot
    ---------------------------------------------------------------------------
    ImportError                               Traceback (most recent call last)
    Input In [1], in <cell line: 1>()
    ----> 1 from matplotlib import pyplot
    
    File ~/git/matplotlib/lib/matplotlib/__init__.py:208, in <module>
        203         if parse_version(module.__version__) < parse_version(minver):
        204             raise ImportError(f"Matplotlib requires {modname}>={minver}; "
        205                               f"you have {module.__version__}")
    --> 208 _check_versions()
        211 # The decorator ensures this always returns the same handler (and it is only
        212 # attached once).
        213 @functools.lru_cache()
        214 def _ensure_handler():
    
    File ~/git/matplotlib/lib/matplotlib/__init__.py:193, in _check_versions()
        189 def _check_versions():
        190
        191     # Quickfix to ensure Microsoft Visual C++ redistributable
        192     # DLLs are loaded before importing kiwisolver
    --> 193     from . import ft2font
        195     for modname, minver in [
        196             ("cycler", "0.10"),
        197             ("dateutil", "2.7"),
       (...)
        200             ("pyparsing", "2.2.1"),
        201     ]:
        202         module = importlib.import_module(modname)
    
    ImportError: /home/mark/git/matplotlib/lib/matplotlib/ft2font.cpython-39-x86_64-linux-gnu.so: undefined symbol: FT_Load_Glyph
    

    Kinda just as hard as I expected it to be (i.e. not to work on the first try).

    The link provided on anaconda installed successfully.

    Finally, it does resolve the problem of allowing you to select the WxAgg backend.

    I then uninstalled it, and reinstalled the version from conda-forge, and it seems to work!

    Thanks all!

  19. tacaswell commented on Apr 1, 2022

    Member

    Oh, that makes sense 😞 . We build our own freetype pinned to a very old version (so the tests will pass because every version of freetype moves the text around a tiny bit) but conda provides a newer one. I suspect at runtime you ended up with crossed libraries....

    I will not claim to understand what the wheel is doing under the hood to make it work though!

  20. hmaarrfk commented on Apr 1, 2022

    ContributorAuthor

    @tacaswell thank you for the hint about freetype. using a slightly modified build script from conda-forge
    https://github.com/conda-forge/matplotlib-feedstock/blob/main/recipe/build_base.sh
    it does indeed import.

    Time for me to sleep. Goodnight

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL