10000 Matplotlib picks a headless backend on Linux if Wayland is available but X11 isn't · Issue #18377 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content
Matplotlib picks a headless backend on Linux if Wayland is available but X11 isn't #18377
Closed
@mstoeckl

Description

@mstoeckl

Bug report

Bug summary

I've been running code using Matplotlib on a Linux computer using a Wayland compositor with X11 disabled. The environment variable DISPLAY is thus not present, although WAYLAND_DISPLAY (or WAYLAND_SOCKET) are. Matplotlib falls back to a headless backend (agg), even though a working display system (Qt5Agg) is available.

Code for reproduction

Any simple code that uses plt.show() should exhibit this behavior.

import matplotlib.pyplot as plt
import matplotlib
print(matplotlib.get_backend())
plt.plot([1,2],[3,4])
plt.show()

Actual outcome

No window appears, code prints "agg".

Expected outcome

Expect a window with the plot to appear, code prints "Qt5Agg"

Matplotlib version

  • Operating system: Linux
  • Matplotlib version: 3.3.1
  • Python version: 3.8.5
  • Wayland compositor: tested with Sway, or Weston
  • Installed via package manager

Current workaround:

To ensure that a GUI backend is selected, instead of a headless one:

diff -r /usr/lib/python3.8/site-packages/matplotlib/cbook/__init__.py ./cbook/__init__.py
74c74
<     if sys.platform.startswith("linux") and not os.environ.get("DISPLAY"):
---
>     if sys.platform.startswith("linux") and not os.environ.get("DISPLAY") and not os.environ.get("WAYLAND_DISPLAY") and not os.environ.get("WAYLAND_SOCKET"):

Why do I check for WAYAND_DISPLAY or WAYLAND_SOCKET to be set, instead of removing this line? It turns out that if these are unset, libwayland (and thus toolkits using it) will by default try to connect to the display "wayland-0". This behavior is horrible when one uses computers with multiple sessions, graphical and not, running, because a script run from an ssh connection might (or might not) lock up and accidentally display something on a monitor in another building.

To ensure that the Qt5Agg backend loads, remove the extra check for DISPLAY's presence. (The code dates back to 9bed016 and 5c222df, where apparently trying and failing to open a Qt4 window was fatal; maybe newer Qt versions let us use the standard try-except approach?)

diff -r /usr/lib/python3.8/site-packages/matplotlib/backends/backend_qt5.py backend_qt5.py
105,120d104
<             # check for DISPLAY env variable on X11 build of Qt
<             if QtCore.qVersion() >= "5.":
<                 try:
<                     importlib.import_module(
<                         # i.e. PyQt5.QtX11Extras or PySide2.QtX11Extras.
<                         f"{QtWidgets.__package__}.QtX11Extras")
<                     is_x11_build = True
<                 except ImportError:
<                     is_x11_build = False
<             else:
<                 is_x11_build = hasattr(QtGui, "QX11Info")
<             if is_x11_build:
<                 display = os.environ.get('DISPLAY')
<                 if display is None or not re.search(r':\d', display):
<                     raise RuntimeError('Invalid DISPLAY variable')
< 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0