GNU bug report logs - #70687
python-matplotlib not respecting env var MPLBACKEND=TkAgg

Previous Next

Package: guix;

Reported by: Jake <jforst.mailman <at> gmail.com>

Date: Wed, 1 May 2024 01:25:01 UTC

Severity: normal

To reply to this bug, email your comments to 70687 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-guix <at> gnu.org:
bug#70687; Package guix. (Wed, 01 May 2024 01:25:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Jake <jforst.mailman <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-guix <at> gnu.org. (Wed, 01 May 2024 01:25:01 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Jake <jforst.mailman <at> gmail.com>
To: bug-guix <at> gnu.org
Subject: python-matplotlib not respecting env var MPLBACKEND=TkAgg
Date: Wed, 1 May 2024 01:23:19 +0000
[Message part 1 (text/plain, inline)]
Hello

We are supposed to be able to control the backend used by Python's
Matplotlib via the MPLBACKEND environment variable [1]. This doesn't appear
to work for the TkAgg backend:

#+begin_src sh

  guix shell python python-matplotlib -- bash -c 'MPLBACKEND=TkAgg python3
-c "import matplotlib; print(matplotlib.get_backend()); import
matplotlib.pyplot as plt; plt.plot([1],[2]); plt.show()"'

#+end_src

#+RESULTS:
: TkAgg
: <string>:1: UserWarning: FigureCanvasAgg is non-interactive, and thus
cannot be shown

However, the TkAgg backend does work if it is hardcoded in the Python
script using `matplotlib.use()`:

#+begin_src sh

  guix shell python python-matplotlib -- python3 -c "import matplotlib;
matplotlib.use('TkAgg'); print(matplotlib.get_backend()); import
matplotlib.pyplot as plt; plt.plot([1],[2]); plt.show()"

#+end_src

#+RESULTS:
: TkAgg

Thanks
Jake

[1]: https://matplotlib.org/stable/users/explain/figure/backends.html
[Message part 2 (text/html, inline)]

Information forwarded to bug-guix <at> gnu.org:
bug#70687; Package guix. (Thu, 03 Apr 2025 11:38:02 GMT) Full text and rfc822 format available.

Message #8 received at 70687 <at> debbugs.gnu.org (full text, mbox):

From: Jake <jforst.mailman <at> gmail.com>
To: 70687 <at> debbugs.gnu.org
Cc: me <at> bonfacemunyoki.com, sharlatanus <at> gmail.com, tanguy <at> bioneland.org,
 lars <at> 6xq.net
Subject: Re: bug#70687: python-matplotlib not respecting env var
 MPLBACKEND=TkAgg
Date: Thu, 3 Apr 2025 11:36:49 +0000
[Message part 1 (text/plain, inline)]
It appears that importing matplotlib.pyplot resets the Matplotlib backend
to Agg.

  $ guix shell python python-matplotlib -- bash -c 'MPLBACKEND=tkagg
python3 -c "import matplotlib; print(matplotlib.get_backend()); import
matplotlib.pyplot; print(matplotlib.get_backend())"'

  TkAgg
  agg


On Wed, May 1, 2024 at 1:25 AM Jake <jforst.mailman <at> gmail.com> wrote:

> Hello
>
> We are supposed to be able to control the backend used by Python's
> Matplotlib via the MPLBACKEND environment variable [1]. This doesn't appear
> to work for the TkAgg backend:
>
> #+begin_src sh
>
>   guix shell python python-matplotlib -- bash -c 'MPLBACKEND=TkAgg python3
> -c "import matplotlib; print(matplotlib.get_backend()); import
> matplotlib.pyplot as plt; plt.plot([1],[2]); plt.show()"'
>
> #+end_src
>
> #+RESULTS:
> : TkAgg
> : <string>:1: UserWarning: FigureCanvasAgg is non-interactive, and thus
> cannot be shown
>
> However, the TkAgg backend does work if it is hardcoded in the Python
> script using `matplotlib.use()`:
>
> #+begin_src sh
>
>   guix shell python python-matplotlib -- python3 -c "import matplotlib;
> matplotlib.use('TkAgg'); print(matplotlib.get_backend()); import
> matplotlib.pyplot as plt; plt.plot([1],[2]); plt.show()"
>
> #+end_src
>
> #+RESULTS:
> : TkAgg
>
> Thanks
> Jake
>
> [1]: https://matplotlib.org/stable/users/explain/figure/backends.html
>
[Message part 2 (text/html, inline)]

Information forwarded to bug-guix <at> gnu.org:
bug#70687; Package guix. (Sat, 05 Apr 2025 23:01:01 GMT) Full text and rfc822 format available.

Message #11 received at 70687 <at> debbugs.gnu.org (full text, mbox):

From: Liliana Marie Prikler <liliana.prikler <at> gmail.com>
To: Jake <jforst.mailman <at> gmail.com>, 70687 <at> debbugs.gnu.org
Cc: me <at> bonfacemunyoki.com, tanguy <at> bioneland.org, sharlatanus <at> gmail.com,
 lars <at> 6xq.net
Subject: Re: bug#70687: python-matplotlib not respecting env var
 MPLBACKEND=TkAgg
Date: Sun, 06 Apr 2025 01:00:44 +0200
Hi Jake,

Am Donnerstag, dem 03.04.2025 um 11:36 +0000 schrieb Jake:
> It appears that importing matplotlib.pyplot resets the Matplotlib
> backend to Agg.
> 
>   $ guix shell python python-matplotlib -- bash -c 'MPLBACKEND=tkagg
> python3 -c "import matplotlib; print(matplotlib.get_backend());
> import matplotlib.pyplot; print(matplotlib.get_backend())"'
> 
>   TkAgg
>   agg
I recently encountered the same issue.  The issue is that matplotlib
internally sources a configuration file that sets the backend *after*
reading the environment variable.  To circumvent this, you use
something along the lines of the following code until the issue is
fixed:

  from matplotlib import set_backend 
  from os import environ
  
  […]

  if __name__ == '__main__':
    if 'MPLBACKEND' in environ: set_backend(environ['MPLBACKEND'])
    […]

Cheers




Information forwarded to bug-guix <at> gnu.org:
bug#70687; Package guix. (Thu, 03 Jul 2025 13:21:01 GMT) Full text and rfc822 format available.

Message #14 received at 70687 <at> debbugs.gnu.org (full text, mbox):

From: Jake <jforst.mailman <at> gmail.com>
To: Liliana Marie Prikler <liliana.prikler <at> gmail.com>
Cc: me <at> bonfacemunyoki.com, 70687 <at> debbugs.gnu.org, tanguy <at> bioneland.org,
 sharlatanus <at> gmail.com, lars <at> 6xq.net
Subject: Re: bug#70687: python-matplotlib not respecting env var
 MPLBACKEND=TkAgg
Date: Thu, 3 Jul 2025 13:19:54 +0000
Hi Lily

It looks like this bug isn't going away anytime soon.

Here is the offending code in `lib/matplotlib/pyplot.py`, with an
added print statement:

```text
# If rcParams['backend_fallback'] is true, and an interactive backend is
# requested, ignore rcParams['backend'] and force selection of a backend that
# is compatible with the current running interactive framework.
if (rcParams["backend_fallback"]
        and rcParams._get_backend_or_none() in (  # type: ignore
            set(rcsetup.interactive_bk) - {'WebAgg', 'nbAgg'})
        and cbook._get_running_interactive_framework()):  # type: ignore
    print(f"running interactive framework is:
{cbook._get_running_interactive_framework()}")
    rcParams._set("backend", rcsetup._auto_backend_sentinel)  # type: ignore
```

Running this

```text
MPLBACKEND=tkagg guix shell
--with-source=python-matplotlib=$HOME/matplotlib
--without-tests=python-matplotlib python python-matplotlib -- python3
-c "import matplotlib; print(matplotlib.get_backend()); import
matplotlib.pyplot as plt; print(matplotlib.get_backend())"
```

gives

```text
TkAgg
running interactive framework is: headless
agg
```

So I guess the next question is: why does it think I'm headless?  To
be continued...

Thanks
Jake


On Sat, Apr 5, 2025 at 11:00 PM Liliana Marie Prikler
<liliana.prikler <at> gmail.com> wrote:
>
> Hi Jake,
>
> Am Donnerstag, dem 03.04.2025 um 11:36 +0000 schrieb Jake:
> > It appears that importing matplotlib.pyplot resets the Matplotlib
> > backend to Agg.
> >
> >   $ guix shell python python-matplotlib -- bash -c 'MPLBACKEND=tkagg
> > python3 -c "import matplotlib; print(matplotlib.get_backend());
> > import matplotlib.pyplot; print(matplotlib.get_backend())"'
> >
> >   TkAgg
> >   agg
> I recently encountered the same issue.  The issue is that matplotlib
> internally sources a configuration file that sets the backend *after*
> reading the environment variable.  To circumvent this, you use
> something along the lines of the following code until the issue is
> fixed:
>
>   from matplotlib import set_backend
>   from os import environ
>
>   […]
>
>   if __name__ == '__main__':
>     if 'MPLBACKEND' in environ: set_backend(environ['MPLBACKEND'])
>     […]
>
> Cheers




Information forwarded to bug-guix <at> gnu.org:
bug#70687; Package guix. (Thu, 03 Jul 2025 13:49:02 GMT) Full text and rfc822 format available.

Message #17 received at 70687 <at> debbugs.gnu.org (full text, mbox):

From: Jake <jforst.mailman <at> gmail.com>
To: Liliana Marie Prikler <liliana.prikler <at> gmail.com>
Cc: me <at> bonfacemunyoki.com, 70687 <at> debbugs.gnu.org, tanguy <at> bioneland.org,
 sharlatanus <at> gmail.com, lars <at> 6xq.net
Subject: Re: bug#70687: python-matplotlib not respecting env var
 MPLBACKEND=TkAgg
Date: Thu, 3 Jul 2025 13:48:25 +0000
Continuing:
In `lib/matplotlib/cbook.py`, the function
`_get_running_interactive_framework` has:

```text
    if not _c_internal_utils.display_is_valid():
        return "headless"
```

In `src/_c_internal_utils.c` we have this docstring for `display_is_valid`:

```text
     "Check whether the current X11 or Wayland display is valid.\n\n"
     "On Linux, returns True if either $DISPLAY is set and XOpenDisplay(NULL)\n"
     "succeeds, or $WAYLAND_DISPLAY is set and wl_display_connect(NULL)\n"
     "succeeds.\n\n"
     "On other platforms, always returns True."},
```

$DISPLAY is set, so it must be XOpenDisplay(NULL) failing...

I found a post [1] from a Nix user:
> For anyone else facing similar issues - I resolved this by adding the X11 library to the LD_LIBRARY_PATH of my development shell.

But I haven't made any more progress.

Cheers
Jake

[1] https://discourse.nixos.org/t/python-matplotlib-tkinter-matplotlib-reverts-to-agg-backend-because-it-cant-find-a-valid-display/45064

On Thu, Jul 3, 2025 at 1:19 PM Jake <jforst.mailman <at> gmail.com> wrote:
>
> Hi Lily
>
> It looks like this bug isn't going away anytime soon.
>
> Here is the offending code in `lib/matplotlib/pyplot.py`, with an
> added print statement:
>
> ```text
> # If rcParams['backend_fallback'] is true, and an interactive backend is
> # requested, ignore rcParams['backend'] and force selection of a backend that
> # is compatible with the current running interactive framework.
> if (rcParams["backend_fallback"]
>         and rcParams._get_backend_or_none() in (  # type: ignore
>             set(rcsetup.interactive_bk) - {'WebAgg', 'nbAgg'})
>         and cbook._get_running_interactive_framework()):  # type: ignore
>     print(f"running interactive framework is:
> {cbook._get_running_interactive_framework()}")
>     rcParams._set("backend", rcsetup._auto_backend_sentinel)  # type: ignore
> ```
>
> Running this
>
> ```text
> MPLBACKEND=tkagg guix shell
> --with-source=python-matplotlib=$HOME/matplotlib
> --without-tests=python-matplotlib python python-matplotlib -- python3
> -c "import matplotlib; print(matplotlib.get_backend()); import
> matplotlib.pyplot as plt; print(matplotlib.get_backend())"
> ```
>
> gives
>
> ```text
> TkAgg
> running interactive framework is: headless
> agg
> ```
>
> So I guess the next question is: why does it think I'm headless?  To
> be continued...
>
> Thanks
> Jake
>
>
> On Sat, Apr 5, 2025 at 11:00 PM Liliana Marie Prikler
> <liliana.prikler <at> gmail.com> wrote:
> >
> > Hi Jake,
> >
> > Am Donnerstag, dem 03.04.2025 um 11:36 +0000 schrieb Jake:
> > > It appears that importing matplotlib.pyplot resets the Matplotlib
> > > backend to Agg.
> > >
> > >   $ guix shell python python-matplotlib -- bash -c 'MPLBACKEND=tkagg
> > > python3 -c "import matplotlib; print(matplotlib.get_backend());
> > > import matplotlib.pyplot; print(matplotlib.get_backend())"'
> > >
> > >   TkAgg
> > >   agg
> > I recently encountered the same issue.  The issue is that matplotlib
> > internally sources a configuration file that sets the backend *after*
> > reading the environment variable.  To circumvent this, you use
> > something along the lines of the following code until the issue is
> > fixed:
> >
> >   from matplotlib import set_backend
> >   from os import environ
> >
> >   […]
> >
> >   if __name__ == '__main__':
> >     if 'MPLBACKEND' in environ: set_backend(environ['MPLBACKEND'])
> >     […]
> >
> > Cheers




Information forwarded to bug-guix <at> gnu.org:
bug#70687; Package guix. (Fri, 04 Jul 2025 08:10:03 GMT) Full text and rfc822 format available.

Message #20 received at 70687 <at> debbugs.gnu.org (full text, mbox):

From: Jake <jforst.mailman <at> gmail.com>
To: Liliana Marie Prikler <liliana.prikler <at> gmail.com>
Cc: me <at> bonfacemunyoki.com, 70687 <at> debbugs.gnu.org, tanguy <at> bioneland.org,
 sharlatanus <at> gmail.com, lars <at> 6xq.net
Subject: Re: bug#70687: python-matplotlib not respecting env var
 MPLBACKEND=TkAgg
Date: Fri, 4 Jul 2025 17:39:13 +0930
[Message part 1 (text/plain, inline)]
Fixed, I think.  We just need to patch a dlopen call.

Now TkAgg works out of the box, without requiring changes to user Python
code.  I hope that also means we can change the default backend from Agg to
TkAgg.

Submitted this PR (and got lucky number 1000!)
https://codeberg.org/guix/guix/pulls/1000
with the fix and change of backend.

Cheers
Jake

On Thu, 3 Jul 2025 at 11:18 pm, Jake <jforst.mailman <at> gmail.com> wrote:

> Continuing:
> In `lib/matplotlib/cbook.py`, the function
> `_get_running_interactive_framework` has:
>
> ```text
>     if not _c_internal_utils.display_is_valid():
>         return "headless"
> ```
>
> In `src/_c_internal_utils.c` we have this docstring for `display_is_valid`:
>
> ```text
>      "Check whether the current X11 or Wayland display is valid.\n\n"
>      "On Linux, returns True if either $DISPLAY is set and
> XOpenDisplay(NULL)\n"
>      "succeeds, or $WAYLAND_DISPLAY is set and wl_display_connect(NULL)\n"
>      "succeeds.\n\n"
>      "On other platforms, always returns True."},
> ```
>
> $DISPLAY is set, so it must be XOpenDisplay(NULL) failing...
>
> I found a post [1] from a Nix user:
> > For anyone else facing similar issues - I resolved this by adding the
> X11 library to the LD_LIBRARY_PATH of my development shell.
>
> But I haven't made any more progress.
>
> Cheers
> Jake
>
> [1]
> https://discourse.nixos.org/t/python-matplotlib-tkinter-matplotlib-reverts-to-agg-backend-because-it-cant-find-a-valid-display/45064
>
> On Thu, Jul 3, 2025 at 1:19 PM Jake <jforst.mailman <at> gmail.com> wrote:
> >
> > Hi Lily
> >
> > It looks like this bug isn't going away anytime soon.
> >
> > Here is the offending code in `lib/matplotlib/pyplot.py`, with an
> > added print statement:
> >
> > ```text
> > # If rcParams['backend_fallback'] is true, and an interactive backend is
> > # requested, ignore rcParams['backend'] and force selection of a backend
> that
> > # is compatible with the current running interactive framework.
> > if (rcParams["backend_fallback"]
> >         and rcParams._get_backend_or_none() in (  # type: ignore
> >             set(rcsetup.interactive_bk) - {'WebAgg', 'nbAgg'})
> >         and cbook._get_running_interactive_framework()):  # type: ignore
> >     print(f"running interactive framework is:
> > {cbook._get_running_interactive_framework()}")
> >     rcParams._set("backend", rcsetup._auto_backend_sentinel)  # type:
> ignore
> > ```
> >
> > Running this
> >
> > ```text
> > MPLBACKEND=tkagg guix shell
> > --with-source=python-matplotlib=$HOME/matplotlib
> > --without-tests=python-matplotlib python python-matplotlib -- python3
> > -c "import matplotlib; print(matplotlib.get_backend()); import
> > matplotlib.pyplot as plt; print(matplotlib.get_backend())"
> > ```
> >
> > gives
> >
> > ```text
> > TkAgg
> > running interactive framework is: headless
> > agg
> > ```
> >
> > So I guess the next question is: why does it think I'm headless?  To
> > be continued...
> >
> > Thanks
> > Jake
> >
> >
> > On Sat, Apr 5, 2025 at 11:00 PM Liliana Marie Prikler
> > <liliana.prikler <at> gmail.com> wrote:
> > >
> > > Hi Jake,
> > >
> > > Am Donnerstag, dem 03.04.2025 um 11:36 +0000 schrieb Jake:
> > > > It appears that importing matplotlib.pyplot resets the Matplotlib
> > > > backend to Agg.
> > > >
> > > >   $ guix shell python python-matplotlib -- bash -c 'MPLBACKEND=tkagg
> > > > python3 -c "import matplotlib; print(matplotlib.get_backend());
> > > > import matplotlib.pyplot; print(matplotlib.get_backend())"'
> > > >
> > > >   TkAgg
> > > >   agg
> > > I recently encountered the same issue.  The issue is that matplotlib
> > > internally sources a configuration file that sets the backend *after*
> > > reading the environment variable.  To circumvent this, you use
> > > something along the lines of the following code until the issue is
> > > fixed:
> > >
> > >   from matplotlib import set_backend
> > >   from os import environ
> > >
> > >   […]
> > >
> > >   if __name__ == '__main__':
> > >     if 'MPLBACKEND' in environ: set_backend(environ['MPLBACKEND'])
> > >     […]
> > >
> > > Cheers
>
[Message part 2 (text/html, inline)]

This bug report was last modified 9 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.