pythonmatplotlibpytestteamcity

Pytests failing on Teamcity due to Matplotlib backend


I'm trying to run some Python unit tests on a remote build server using Teamcity. They fail when attempting to execute some matplotlib code. I get the following output in the Teamcity build logs, which seems to point towards the matplotlib backend as the culprit.

    XXXXX\stats.py:144: in PerformHypothesisTest
        fig, ax = plt.subplots(1, 1, figsize=(10, 6))
    .venv\lib\site-packages\matplotlib\pyplot.py:1702: in subplots
        fig = figure(**fig_kw)
    .venv\lib\site-packages\matplotlib\pyplot.py:1022: in figure
        manager = new_figure_manager(
    .venv\lib\site-packages\matplotlib\pyplot.py:545: in new_figure_manager
        return _get_backend_mod().new_figure_manager(*args, **kwargs)
    .venv\lib\site-packages\matplotlib\backend_bases.py:3521: in new_figure_manager
        return cls.new_figure_manager_given_figure(num, fig)
    .venv\lib\site-packages\matplotlib\backend_bases.py:3526: in new_figure_manager_given_figure
        return cls.FigureCanvas.new_manager(figure, num)
    .venv\lib\site-packages\matplotlib\backend_bases.py:1811: in new_manager
        return cls.manager_class.create_with_canvas(cls, figure, num)
    .venv\lib\site-packages\matplotlib\backends\_backend_tk.py:479: in create_with_canvas
        with _restore_foreground_window_at_end():
    C:\Python310\lib\contextlib.py:135: in __enter__
        return next(self.gen)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
        @contextmanager
        def _restore_foreground_window_at_end():
    >       foreground = _c_internal_utils.Win32_GetForegroundWindow()
    E       ValueError: PyCapsule_New called with null pointer
    
    .venv\lib\site-packages\matplotlib\backends\_backend_tk.py:43: ValueError

The tests run fine both:

I'm not super familiar with how Teamcity works and how to debug it, so I would appreciate any ideas as to what might be going wrong here.

The build server is running the following versions:

If it is useful, the build server is using the 'tkagg' backend (from matplotlib.get_backend()).

Update: Thanks for the responses. As snark says, the issue seems to be due to a bug in the most recent Matplotlib release (3.9.0). Until this is fixed, I've dealt with this by explicitly setting the Matplotlib backend to 'Agg' as suggested by BadCaffe and Lemmy. I did this programmatically via a pytest conftest.py file.


Solution

  • I had the same Issue, it has something to do with the missing physical video out (on a server with a nightly build, you usually have no monitor connected). This is why it works on your private machine.

    matplotlib.use('Agg')
    

    should work, but if you have completely automatic nightly builds, that pull down some kind of repository and you can not alter the code, look here: https://matplotlib.org/stable/users/explain/customizing.html#the-matplotlibrc-file

    You can place a "matplotlibrc" file in the user folder (depending on your os) and simply put "backend : Agg" in there. This does the same thing as matplotlib.use('Agg') in changing the used backend, but you can do it without changing the code.