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 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 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 > > 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 >