Matplotlib behaves differently local vs github

We’re struggling to get matplotlib to render figures on github. In the preview and local (nbdev_docs) environments figures are rendered properly. On github some calls that should render a figure are yielding the text representation (“<Figure size 1000x600 with 1 Axes>”) and some are yielding the figure. My code defines a class who’s instance method can produce a plot on-demand. That method renders figures fine in both environments. Another class includes an instance of the original class as one of its attributes. The call to produce a figure from the second class works locally, but not on github. i.e. Class2.class1instance.make_plot(). I’m not convinced that is the relevant difference between the two, but I haven’t found much else.

I’ve played around with a number of things to coax matplotlib into displaying a figure including plt.show() and a variety of return types from the function. I’ve explored the environment differences a bit as well. There are some version number differences, but the changelogs don’t indicate anything relevant. Differences are for ipykernel 6.29.4 vs …3, various jupyter components, matplotlib 3.7.5 vs …4, matplotlib-inline not present vs 0.1.6. That last sounds relevant, but I currently have the plot function printing the backend every time and it is always inline (“module://matplotlib_inline.backend_inline”).

I can confirm that this is happening in nbdev processing not in quarto rendering, as I am archiving and reviewing the contents of the _proc directory on github.

Has anyone experienced similar behavior?

So it turns out the code structure has nothing to do with it. I placed a generic plot test at the beginning of the second file, and I get the same behavior. Plots work in one but not the other. The matplotlib imports are done the same way in both. Is there potential that notebook execution environments in nbdev_docs are not completely independent? Or is there a resource problem here?

Another update: I realized that the execution order on gh was different from what was happening locally, resulting from os.walk’s filesystem dependent behavior. The notebook with the functional matplotlib plots executes earlier on gh, but later on gh. The other notebook executes later on gh, but earlier locally. I was able to reverse the order locally by stuffing the notebook with broken plot into a subdirectory. This is the first time I’ve been able to replicate the problem locally.

Oddly the broken plots get fixed when that notebook executes earlier, but the originally working plots don’t break when their notebook executes later.

Ok I’ve been able to replicate this locally finally. It’s not exactly what I expected, but here’s what I see so far.

I have an independent project with 3 notebooks (with matplotlib statements, a few others that don’t), each with simple meaningless plot generation. When I execute with 1 worker (nbdev_docs --n_workers 1), the first notebook’s plots work and the following don’t. When I execute with 2 workers, the first two notebooks’ plots work and the final one doesn’t. When I execute with 3 workers, all three notebooks produce plots properly.

From this I would conclude that something about not being the first notebook executed by a [worker] is causing matplotlib to fail. At this point I’ll go ahead and make a bug report as well.