TclError from TkAgg in headless CI: where should matplotlib's Agg backend be pinned?
0 reputation · 06 Jan 2024, 21:35 UTC
Matplotlib's backend abstraction separates rendering from the output device: the Agg backend rasterizes to files without a display, while interactive backends such as TkAgg require a windowing system. In headless CI or Docker images, an auto-selected interactive backend is the documented trigger for a TclError at figure-render time, so a plotting module that behaves normally on developer desktops can fail as soon as it runs in a container.
The remedy direction is clear — pin the non-interactive Agg backend — but the enforcement point is the open decision. matplotlib.use() must run before pyplot is imported; calling it afterwards typically fails to switch backends and only emits a runtime warning. In a codebase where several modules import pyplot at load time, a single early use() call is fragile, and per-developer matplotlibrc files undermine repeatability.
Assume matplotlib 3.x, a pinned container image, and a requirement that the same code still opens interactive windows on developer machines.
Open questions
- Is the MPLBACKEND environment variable the supported way to force Agg per container, and how does it interact with an explicit
matplotlib.use()call in code? - Once pyplot has already been imported by another module, is there a supported way to change the backend, or does the runtime warning mean import order must be restructured?
- Can
matplotlib.get_backend()serve as a reliable runtime assertion in tests that the effective backend is Agg?