Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Bug]: backend error when in use on Windows #25269

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

Closed
malishmali opened this issue Feb 20, 2023 · 1 comment
Closed

[Bug]: backend error when in use on Windows #25269

malishmali opened this issue Feb 20, 2023 · 1 comment

Comments

@malishmali
Copy link

malishmali commented Feb 20, 2023

Bug summary

matplotlib using 'module://backend_interagg' as backend on Windows, causes the error below. Was not an issue prior to 3.7.0 version release. Fixed by using matplotlib.use("TkAgg").

Code for reproduction

import matplotlib.pyplot as plt
plt.clf()

Actual outcome

..\ael_abaqus\access.py:119: in run
    plotting_inst.plot_set("Reaction", y_data)
..\ael_abaqus\access_plotting.py:223: in plot_set
    p = Plot2D()
..\ael_abaqus\access_plot2d.py:25: in _init_
    plt.clf()
..\venv\lib\site-packages\matplotlib\pyplot.py:970: in clf
    gcf().clear()
..\venv\lib\site-packages\matplotlib\pyplot.py:879: in gcf
    return figure()
..\venv\lib\site-packages\matplotlib\_api\deprecation.py:454: in wrapper
    return func(*args, **kwargs)
..\venv\lib\site-packages\matplotlib\pyplot.py:813: in figure
    manager = new_figure_manager(
..\venv\lib\site-packages\matplotlib\pyplot.py:382: in new_figure_manager
    _warn_if_gui_out_of_main_thread()
..\venv\lib\site-packages\matplotlib\pyplot.py:360: in _warn_if_gui_out_of_main_thread
    if _get_required_interactive_framework(_get_backend_mod()):
..\venv\lib\site-packages\matplotlib\pyplot.py:208: in _get_backend_mod
    switch_backend(rcParams._get("backend"))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
newbackend = 'module://backend_interagg'
    def switch_backend(newbackend):
        """
        Set the pyplot backend.
    
        Switching to an interactive backend is possible only if no event loop for
        another interactive backend has started.  Switching to and from
        non-interactive backends is always possible.
    
        If the new backend is different than the current backend then all open
        Figures will be closed via ``plt.close('all')``.
    
        Parameters
        ----------
        newbackend : str
            The case-insensitive name of the backend to use.
    
        """
        global _backend_mod
        # make sure the init is pulled up so we can assign to it later
        import matplotlib.backends
    
        if newbackend is rcsetup._auto_backend_sentinel:
            current_framework = cbook._get_running_interactive_framework()
            mapping = {'qt': 'qtagg',
                       'gtk3': 'gtk3agg',
                       'gtk4': 'gtk4agg',
                       'wx': 'wxagg',
                       'tk': 'tkagg',
                       'macosx': 'macosx',
                       'headless': 'agg'}
    
            best_guess = mapping.get(current_framework, None)
            if best_guess is not None:
                candidates = [best_guess]
            else:
                candidates = []
            candidates += [
                "macosx", "qtagg", "gtk4agg", "gtk3agg", "tkagg", "wxagg"]
    
            # Don't try to fallback on the cairo-based backends as they each have
            # an additional dependency (pycairo) over the agg-based backend, and
            # are of worse quality.
            for candidate in candidates:
                try:
                    switch_backend(candidate)
                except ImportError:
                    continue
                else:
                    rcParamsOrig['backend'] = candidate
                    return
            else:
                # Switching to Agg should always succeed; if it doesn't, let the
                # exception propagate out.
                switch_backend("agg")
                rcParamsOrig["backend"] = "agg"
                return
        # have to escape the switch on access logic
        old_backend = dict._getitem_(rcParams, 'backend')
    
        backend_mod = importlib.import_module(
            cbook._backend_module_name(newbackend))
    
        required_framework = _get_required_interactive_framework(backend_mod)
        if required_framework is not None:
            current_framework = cbook._get_running_interactive_framework()
            if (current_framework and required_framework
                    and current_framework != required_framework):
                raise ImportError(
                    "Cannot load backend {!r} which requires the {!r} interactive "
                    "framework, as {!r} is currently running".format(
                        newbackend, required_framework, current_framework))
    
        # Load the new_figure_manager() and show() functions from the backend.
    
        # Classically, backends can directly export these functions.  This should
        # keep working for backcompat.
        new_figure_manager = getattr(backend_mod, "new_figure_manager", None)
        show = getattr(backend_mod, "show", None)
    
        # In that classical approach, backends are implemented as modules, but
        # "inherit" default method implementations from backend_bases._Backend.
        # This is achieved by creating a "class" that inherits from
        # backend_bases._Backend and whose body is filled with the module globals.
        class backend_mod(matplotlib.backend_bases._Backend):
            locals().update(vars(backend_mod))
    
        # However, the newer approach for defining new_figure_manager and
        # show is to derive them from canvas methods.  In that case, also
        # update backend_mod accordingly; also, per-backend customization of
        # draw_if_interactive is disabled.
        if new_figure_manager is None:
            # Only try to get the canvas class if have opted into the new scheme.
            canvas_class = backend_mod.FigureCanvas
    
            def new_figure_manager_given_figure(num, figure):
                return canvas_class.new_manager(figure, num)
    
            def new_figure_manager(num, *args, FigureClass=Figure, **kwargs):
                fig = FigureClass(*args, **kwargs)
                return new_figure_manager_given_figure(num, fig)
    
            def draw_if_interactive():
                if matplotlib.is_interactive():
                    manager = _pylab_helpers.Gcf.get_active()
                    if manager:
                        manager.canvas.draw_idle()
    
            backend_mod.new_figure_manager_given_figure = \
                new_figure_manager_given_figure
            backend_mod.new_figure_manager = new_figure_manager
            backend_mod.draw_if_interactive = draw_if_interactive
    
        # If the manager explicitly overrides pyplot_show, use it even if a global
        # show is already present, as the latter may be here for backcompat.
        manager_class = getattr(getattr(backend_mod, "FigureCanvas", None),
                                "manager_class", None)
        # We can't compare directly manager_class.pyplot_show and FMB.pyplot_show
        # because pyplot_show is a classmethod so the above constructs are bound
        # classmethods, & thus always different (being bound to different classes).
      manager_pyplot_show = vars(manager_class).get("pyplot_show")
E       TypeError: vars() argument must have _dict_ attribute
..\venv\lib\site-packages\matplotlib\pyplot.py:331: TypeError

Expected outcome

Ideally shouldn't have to include matplotlib.use("TkAgg") manually because it causes errors with the script when ran not on windows.

Additional information

Other person encountering the same error: https://stackoverflow.com/questions/75453995/pandas-plot-vars-argument-must-have-dict-attribute

Operating system

No response

Matplotlib Version

3.7.0

Matplotlib Backend

module://backend_interagg

Python version

3.8.10

Jupyter version

No response

Installation

pip

@oscargus
Copy link
Member

This was fixed in #25240 and will be included in 3.7.1.

@QuLogic QuLogic added this to the v3.7.1 milestone Jul 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants