The bug revolves around the interaction between tkinter and matplotlib, while using PdfPages. Specifically, somehow a call to pyplot.close() let's the current 'module' finish but afterwards the tk.Tk() instance is closed without warning/error (see the attached MVE code). I expect that this is a bug in the matplotlib domain after hearing that this occurs more often (https://stackoverflow.com/q/54772180/1093485).
This does not occur in matplotlib 3.0.2. Very likely it has been fixed by #12707. It has however not been backported to 2.2 Not sure what's going on, it sometimes works, sometimes not.
Now I'm really lost. I can reproduce this with any mpl version, and any of the two tk versions if this is being run from the command line. If however I run it from within Spyder with the setting "Use external system command" (which I would have thought to be identical to the CLI) it works as expected. (In both cases adding matplotlib.use("TkAgg"), as other backends don't show this issue)
which quits the application when all of the figures are closed. This is essential for plt.show(block=True) to work (so when you close all of the plots we return control to the terminal). Is there a way to ask tk "do you still have any windows open" to trigger that logic on instead?
In this case do you want to show the figures as interactive tk windows or just save pdf? In the former I think you may have to do the embedding your self, if the later, picking a non-interactive backend is probably the correct solution.
I have no guesses as to why in is working is spyder though...
The program should be able to have plots open in it's own GUI or create plots in a PDF report (depending on the user selection). Would it in any way be useful for you to see the full code of how I was using this?
I think I may always have mis-interpreted the meaning of a non-interactive backend as using simply ('Agg') fixes this issue for my system, while still providing the option to interact with the plot inside the tkinter window.
This is yet another of the points of tension in Matplotlib between providing a low-level library to be used by application developers and being a front-line user interface. It this case, the niceties we need to provide for the end-user (ex, exiting the GUI main loop when the last figure is closed) is conflicting with how @Tarskin wants to use Matplot as a low-level library.
@Tarskin "interactive" means we hook up all the mouse / keyboard listeners + embedded the image of the plot in a native-GUI window + re-draw on changes + do some rudimentary hooking into the GUI main loop (basically, all the details that need to happen for plt.ion(); plt.plot(range(5)) to pop up a 'live' window you can pan / zoom / mutate and have it 'do the right thing')
The plotting was already embedded in the GUI part, and I was trying to be 'simple' in my Pdf class that created the PDF reports. I am now refactoring those to use Figure instead, which I didn't consider. I do want to check if I understood you correctly, in suggesting that one should never use pyplot in a stand-alone and instead resort to always working with the Figure class?
I will admit that just using the Figure class directly, makes it much simpler as the underlying logic is then the same for the gui and the reports, I should have considered that to begin with. Thanks for the tip!
Activity
ImportanceOfBeingErnest commented on Feb 19, 2019
This does not occur in matplotlib 3.0.2. Very likely it has been fixed by #12707. It has however not been backported to 2.2 Not sure what's going on, it sometimes works, sometimes not.
Tarskin commented on Feb 19, 2019
I am still encountering the issue after upgrading to 3.0.2 (TkAgg backend), with the above code snippet.
ImportanceOfBeingErnest commented on Feb 19, 2019
What is your exact version of Tk? With TK version 8.6.8 I cannot reproduce this, while it appears to fail with 8.6.7.
Tarskin commented on Feb 19, 2019
I think simply 8.6 as that's what tkinter.TkVersion lists, unless that lists only major versions somehow.
ImportanceOfBeingErnest commented on Feb 19, 2019
Now I'm really lost. I can reproduce this with any mpl version, and any of the two tk versions if this is being run from the command line. If however I run it from within Spyder with the setting "Use external system command" (which I would have thought to be identical to the CLI) it works as expected. (In both cases adding matplotlib.use("TkAgg"), as other backends don't show this issue)
tacaswell commented on Feb 20, 2019
The "problem" is the logic in
matplotlib/lib/matplotlib/backends/_backend_tk.py
Lines 553 to 562 in a276243
In this case do you want to show the figures as interactive tk windows or just save pdf? In the former I think you may have to do the embedding your self, if the later, picking a non-interactive backend is probably the correct solution.
I have no guesses as to why in is working is spyder though...
tacaswell commented on Feb 20, 2019
moved to 3.2 as this is not a regression.
Tarskin commented on Feb 20, 2019
The program should be able to have plots open in it's own GUI or create plots in a PDF report (depending on the user selection). Would it in any way be useful for you to see the full code of how I was using this?
I think I may always have mis-interpreted the meaning of a non-interactive backend as using simply ('Agg') fixes this issue for my system, while still providing the option to interact with the plot inside the tkinter window.
tacaswell commented on Feb 20, 2019
See https://matplotlib.org/gallery/user_interfaces/embedding_in_tk_sgskip.html for how to do a 'full embedding'. If you are writing a stand-alone application, I strongly suggest going that route and not even importing pyplot.
This is yet another of the points of tension in Matplotlib between providing a low-level library to be used by application developers and being a front-line user interface. It this case, the niceties we need to provide for the end-user (ex, exiting the GUI main loop when the last figure is closed) is conflicting with how @Tarskin wants to use Matplot as a low-level library.
@Tarskin "interactive" means we hook up all the mouse / keyboard listeners + embedded the image of the plot in a native-GUI window + re-draw on changes + do some rudimentary hooking into the GUI main loop (basically, all the details that need to happen for plt.ion(); plt.plot(range(5)) to pop up a 'live' window you can pan / zoom / mutate and have it 'do the right thing')
Tarskin commented on Feb 20, 2019
The plotting was already embedded in the GUI part, and I was trying to be 'simple' in my Pdf class that created the PDF reports. I am now refactoring those to use Figure instead, which I didn't consider. I do want to check if I understood you correctly, in suggesting that one should never use pyplot in a stand-alone and instead resort to always working with the Figure class?
I will admit that just using the Figure class directly, makes it much simpler as the underlying logic is then the same for the gui and the reports, I should have considered that to begin with. Thanks for the tip!
tacaswell commented on Feb 20, 2019
https://matplotlib.org/tutorials/introductory/usage.html#coding-styles may also be a useful link (but it sounds like you already figured out everything in there!).
I am going to go ahead and close this as it sounds like this is primarily a conflict in usage and not a bug we can fix.
anntzer commented on Feb 20, 2019
I think we could at least try to not close the main Tk instance as long as there are windows (not managed by matplotlib) left open?
tacaswell commented on Feb 25, 2019
That is a fair point, re-opening.
Tagging as good first issue as this is primarily an issue with how we use Tk (rather than Matplotlib internals).
sameshl commented on Aug 11, 2019
@tacaswell Could you summarize what should be done here? I would love to contribute to this.
richardsheridan commented on Jun 30, 2020
@tacaswell This looks fixable but the fix is not pretty without help from upstream, see #17802.