Matplotlib, Tk, and multithreading

Hi,

I have a library which uses matplotlib to produce some plots. This library is called by a thread. However, python crashes with this error when it tries to plot something:

Tk_MacOSXSetupTkNotifier: first [load] of TkAqua has to occur in the main thread!

If I do as it says and call "window = Tkinter.Tk()" in the main thread before spawning the thread which calls the plotting routines, it works well until the program shuts down. When shutting down, I get a series of these messages (8 of them, to be precise):

Exception RuntimeError: RuntimeError('main thread is not in main loop',) in <bound method PhotoImage.__del__ of <Tkinter.PhotoImage instance at 0x90fe260>> ignored

Googling reveals to me that this is a problem with Tk: it doesn't like threading. I tried to force matplotlib to use a different backend with this command:
matplotlib.rcParams['backend'] = something_else
but it still crashes with the first error.

Has anyone encountered this problem before? How did you overcome it?

Cheers,
Oliver

Are you displaying the plots in the thread, or are you just saving the plots directly? If you are saving them directly, then you can set your backend to be “Agg” and get rid of the Tkinter.Tk() call (and probably should get rid of the import as well). That way, matplotlib won’t load up any gui toolkits at all.

Cheers!
Ben Root

···

On Wed, Mar 13, 2013 at 9:43 PM, Oliver King <oliver.africa@…287…> wrote:

Hi,

I have a library which uses matplotlib to produce some plots. This library is called by a thread. However, python crashes with this error when it tries to plot something:

Tk_MacOSXSetupTkNotifier: first [load] of TkAqua has to occur in the main thread!

If I do as it says and call “window = Tkinter.Tk()” in the main thread before spawning the thread which calls the plotting routines, it works well until the program shuts down. When shutting down, I get a series of these messages (8 of them, to be precise):

Exception RuntimeError: RuntimeError(‘main thread is not in main loop’,) in <bound method PhotoImage.del of <Tkinter.PhotoImage instance at 0x90fe260>> ignored

Googling reveals to me that this is a problem with Tk: it doesn’t like threading. I tried to force matplotlib to use a different backend with this command:

matplotlib.rcParams[‘backend’] = something_else

but it still crashes with the first error.

Has anyone encountered this problem before? How did you overcome it?

Hi Ben,

Are you displaying the plots in the thread, or are you just saving the plots directly? If you are saving them directly, then you can set your backend to be "Agg" and get rid of the Tkinter.Tk() call (and probably should get rid of the import as well). That way, matplotlib won't load up any gui toolkits at all.

I'm saving the plots directly (plt.figure();plt.plot();plt.savefig();plt.close(fig)). I tried doing as you suggested [don't import Tk directly and change the backend to Agg] but it still crashes with the same TkAqua message. I don't explicitly import or use Tk anywhere in my code, so it seems that matplotlib is trying to load it anyway even when instructed to use a different backend.

I'm running Enthought Python 7.3-2 on Mac OS X 10.6.8. Note that this problem seems to be restricted to this particular operating system; when I run the code on CentOS, also using EPD 7.3-2, it does not crash.

Cheers,
Oliver

2013/3/14 Oliver King <oliver.africa@...287...>:

[...]
I tried doing as you suggested [don't import Tk directly and change the backend to Agg] but it still crashes with the same TkAqua message.

You must set the desired backend from the very begining and before
importing pylab o pyplot.

Goyo

You must set the desired backend from the very begining and before
importing pylab o pyplot.

That did it - I made the change in my .matplotlibrc file and it no longer crashes.

Thanks!
Oliver