Hello,
After a lot of test… I still can not figure out why the Azure pipeline for a repository I maintain is randomly, and I insist on the randomly, failing. I would appreciate any help from experienced dev!
I’m running a pipeline on the windows-latest
image, with python versions ranging from 3.7 to 3.10. Here is the pipeline: pycrostates/azure-pipelines.yml at 555ef8db65755dd415ae075e53b7cd4b03f69edf · vferat/pycrostates · GitHub
It’s nothing fancy, it retrieves from cache a testing dataset or downloads it and then runs the unit tests with pytest
. But, the windows runner will randomly fail during the tests (usually 1 or 2 out of the 4 python versions) with 2 errors related to matplotlib
and Tcl
.
The first one: _tkinter.TclError: invalid command name "tcl_findLibrary"
def test_plot_segmentation(ModK, inst):
"""Test the plot of a segmentation."""
segmentation = ModK.predict(inst)
segmentation.plot()
plt.close("all")
> segmentation.plot(cmap="plasma")
pycrostates\segmentation\tests\test_segmentation.py:194:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
pycrostates\segmentation\segmentation.py:395: in plot
verbose=verbose,
pycrostates\viz\segmentation.py:77: in plot_raw_segmentation
**kwargs,
pycrostates\viz\segmentation.py:205: in _plot_segmentation
fig, axes = plt.subplots(1, 1)
C:\hostedtoolcache\windows\Python\3.7.9\x64\lib\site-packages\matplotlib\pyplot.py:1455: in subplots
fig = figure(**fig_kw)
C:\hostedtoolcache\windows\Python\3.7.9\x64\lib\site-packages\matplotlib\pyplot.py:811: in figure
FigureClass=FigureClass, **kwargs)
C:\hostedtoolcache\windows\Python\3.7.9\x64\lib\site-packages\matplotlib\pyplot.py:327: in new_figure_manager
return _get_backend_mod().new_figure_manager(*args, **kwargs)
C:\hostedtoolcache\windows\Python\3.7.9\x64\lib\site-packages\matplotlib\backend_bases.py:3494: in new_figure_manager
return cls.new_figure_manager_given_figure(num, fig)
C:\hostedtoolcache\windows\Python\3.7.9\x64\lib\site-packages\matplotlib\backends\_backend_tk.py:949: in new_figure_manager_given_figure
window = tk.Tk(className="matplotlib")
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <tkinter.Tk object .>, screenName = None, baseName = 'pytest'
className = 'matplotlib', useTk = 1, sync = 0, use = None
def __init__(self, screenName=None, baseName=None, className='Tk',
useTk=1, sync=0, use=None):
"""Return a new Toplevel widget on screen SCREENNAME. A new Tcl interpreter will
be created. BASENAME will be used for the identification of the profile file (see
readprofile).
It is constructed from sys.argv[0] without extensions if None is given. CLASSNAME
is the name of the widget class."""
self.master = None
self.children = {}
self._tkloaded = 0
# to avoid recursions in the getattr code in case of failure, we
# ensure that self.tk is always _something_.
self.tk = None
if baseName is None:
import os
baseName = os.path.basename(sys.argv[0])
baseName, ext = os.path.splitext(baseName)
if ext not in ('.py', '.pyc'):
baseName = baseName + ext
interactive = 0
> self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
E _tkinter.TclError: invalid command name "tcl_findLibrary"
Note that it does not always occur in the same test, e.g. same error in a different run:
def test_check_axes():
"""Test _check_axes checker."""
# test valid inputs
> _, ax = plt.subplots(1, 1)
pycrostates\utils\tests\test_checks.py:114:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\hostedtoolcache\windows\Python\3.8.10\x64\lib\site-packages\matplotlib\pyplot.py:1455: in subplots
fig = figure(**fig_kw)
C:\hostedtoolcache\windows\Python\3.8.10\x64\lib\site-packages\matplotlib\pyplot.py:808: in figure
manager = new_figure_manager(
C:\hostedtoolcache\windows\Python\3.8.10\x64\lib\site-packages\matplotlib\pyplot.py:327: in new_figure_manager
return _get_backend_mod().new_figure_manager(*args, **kwargs)
C:\hostedtoolcache\windows\Python\3.8.10\x64\lib\site-packages\matplotlib\backend_bases.py:3494: in new_figure_manager
return cls.new_figure_manager_given_figure(num, fig)
C:\hostedtoolcache\windows\Python\3.8.10\x64\lib\site-packages\matplotlib\backends\_backend_tk.py:949: in new_figure_manager_given_figure
window = tk.Tk(className="matplotlib")
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <tkinter.Tk object .>, screenName = None, baseName = 'pytest'
className = 'matplotlib', useTk = 1, sync = 0, use = None
def __init__(self, screenName=None, baseName=None, className='Tk',
useTk=1, sync=0, use=None):
"""Return a new Toplevel widget on screen SCREENNAME. A new Tcl interpreter will
be created. BASENAME will be used for the identification of the profile file (see
readprofile).
It is constructed from sys.argv[0] without extensions if None is given. CLASSNAME
is the name of the widget class."""
self.master = None
self.children = {}
self._tkloaded = False
# to avoid recursions in the getattr code in case of failure, we
# ensure that self.tk is always _something_.
self.tk = None
if baseName is None:
import os
baseName = os.path.basename(sys.argv[0])
baseName, ext = os.path.splitext(baseName)
if ext not in ('.py', '.pyc'):
baseName = baseName + ext
interactive = 0
> self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
E _tkinter.TclError: invalid command name "tcl_findLibrary"
And the second error: _tkinter.TclError: Can't find a usable init.tcl
def test_check_axes():
"""Test _check_axes checker."""
# test valid inputs
> _, ax = plt.subplots(1, 1)
pycrostates\utils\tests\test_checks.py:114:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\hostedtoolcache\windows\Python\3.9.13\x64\lib\site-packages\matplotlib\pyplot.py:1455: in subplots
fig = figure(**fig_kw)
C:\hostedtoolcache\windows\Python\3.9.13\x64\lib\site-packages\matplotlib\pyplot.py:808: in figure
manager = new_figure_manager(
C:\hostedtoolcache\windows\Python\3.9.13\x64\lib\site-packages\matplotlib\pyplot.py:327: in new_figure_manager
return _get_backend_mod().new_figure_manager(*args, **kwargs)
C:\hostedtoolcache\windows\Python\3.9.13\x64\lib\site-packages\matplotlib\backend_bases.py:3494: in new_figure_manager
return cls.new_figure_manager_given_figure(num, fig)
C:\hostedtoolcache\windows\Python\3.9.13\x64\lib\site-packages\matplotlib\backends\_backend_tk.py:949: in new_figure_manager_given_figure
window = tk.Tk(className="matplotlib")
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <tkinter.Tk object .>, screenName = None, baseName = 'pytest'
className = 'matplotlib', useTk = True, sync = False, use = None
def __init__(self, screenName=None, baseName=None, className='Tk',
useTk=True, sync=False, use=None):
"""Return a new Toplevel widget on screen SCREENNAME. A new Tcl interpreter will
be created. BASENAME will be used for the identification of the profile file (see
readprofile).
It is constructed from sys.argv[0] without extensions if None is given. CLASSNAME
is the name of the widget class."""
self.master = None
self.children = {}
self._tkloaded = False
# to avoid recursions in the getattr code in case of failure, we
# ensure that self.tk is always _something_.
self.tk = None
if baseName is None:
import os
baseName = os.path.basename(sys.argv[0])
baseName, ext = os.path.splitext(baseName)
if ext not in ('.py', '.pyc'):
baseName = baseName + ext
interactive = False
> self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
E _tkinter.TclError: Can't find a usable init.tcl in the following directories:
E {C:\hostedtoolcache\windows\Python\3.9.13\x64\tcl\tcl8.6}
E
E C:/hostedtoolcache/windows/Python/3.9.13/x64/tcl/tcl8.6/init.tcl: couldn't read file "C:/hostedtoolcache/windows/Python/3.9.13/x64/tcl/tcl8.6/init.tcl": No error
E couldn't read file "C:/hostedtoolcache/windows/Python/3.9.13/x64/tcl/tcl8.6/init.tcl": No error
E while executing
E "uplevel #0 [list source $tclfile]"
E
E
E This probably means that Tcl wasn't installed properly.
I am completely out of idea, does anyone has a good suggestion on how to fix it and make this CI workflow stable and reliable?