Threading - Matplotlib - main thread is not in main loop - Tcl_AsyncDelete

6,660 views
Skip to first unread message

Martin Fayad

unread,
Aug 9, 2016, 7:54:58 AM8/9/16
to Kivy users support
Hey guys. I have a problem. I made a GUI in which you SETS parameters for Matplotlib graph and then with a START Button a new Thread is started and this Thread opens/creates a Matplotlib-Graph outside the GUI(not as a widget).
The reason i use new thread is that I dont want to have frozen GUI while the Graph window is open

Everything works fine. But as a rule, everytime i close the GUI, python post this or only part of the error shown below. Thats not really a problem as it is after closing the GUI. What is a problem is that the GUI everytime after some time crashes giving similar or same error:


 Exception ignored in: <bound method PhotoImage.__del__ of <tkinter.PhotoImage object at 0x0B411DB0>>
 Traceback (most recent call last):
   File "C:\Python34\lib\tkinter\__init__.py", line 3383, in __del__
     self.tk.call('image', 'delete', self.name)
 RuntimeError: main thread is not in main loop
Tcl_AsyncDelete: async handler deleted by the wrong thread

I am new to python and also to kivy so i cant really get what is the problem.
I tried the new thread outside the root gui class. I tried it outside the root class. Everytime the same.

Maybe the problem is that i dont really understand the deep working of GUIs. How Imagine it is that GUI is the main thread, so if I open Graph, GUI must stops ltill the graph is closed... That works. So I dont really understand why it crashes when I create paralel thread that process the Graph.

Thanks for reading
    Martin
 
PS: if the code is needed

Sorry for lame code:


class STORAGEofVARIABLES():
COLORS={'red':'r','yellow':'y','blue':'b','green':'g','magenta':'m','black':'k','cyan':'c'}
pass

STORAGE=STORAGEofVARIABLES()





class gui(BoxLayout):
PlotActive=0
COLORS={'red':'r','yellow':'y','blue':'b','green':'g','magenta':'m','black':'k','cyan':'c'}
##VALUES

def __init__(self, *args, **kwargs):
super(gui, self).__init__(*args, **kwargs)
#Clock.schedule_interval(self.Thr, 1.5)

def Thr(self):
print('------')
print('Number of Active Threads:' + str(threading.active_count()))
print('Current working Thread: '+str(threading.current_thread().name))
print('------')






def save_values(self):
OsaX = self.ids.OsaX
OsaY = self.ids.OsaY
Hodnota=self.ids.slajd
Code=self.ids.codas
COLORKA=self.ids.spin
MARKER=self.ids.MarkSpinner
GRID=self.ids.grid
TLEGEND=self.ids.tlegenda
LEGEND=self.ids.legenda
TITLEGRAPH=self.ids.Titlegraph
STORAGE.Y_LABEL = OsaY.text
STORAGE.X_LABEL = OsaX.text
STORAGE.TITLE_LABEL = TITLEGRAPH.text
STORAGE.CODE = Code.text
STORAGE.SLIDER_VALUE = Hodnota.value
STORAGE.GRID = GRID.active
STORAGE.TLEGEND = TLEGEND.text
STORAGE.LEGEND = LEGEND.active
STORAGE.COLORKA = COLORKA.text
STORAGE.MARKER=MARKER.text
STORAGE.PlotActive = threading.active_count()
STORAGE.MARKER=MARKER.text

Thread() # Start the thread






def Thread():
t = threading.Thread(target=BasicGraph)
t.daemon = True
t.start()

def BasicGraph():
x, y = [], []
loc = {}
try:
exec(STORAGE.CODE, {}, loc)
x = loc['x']
y = loc['y']
except:
print("Chyba v kodu")
plt.plot(x, y, label=STORAGE.TLEGEND, marker=STORAGE.MARKER, linewidth=STORAGE.SLIDER_VALUE,
color=STORAGE.COLORS[STORAGE.COLORKA])
if STORAGE.LEGEND == True:
plt.legend()
if STORAGE.GRID == True:
plt.grid(color=STORAGE.COLORS[STORAGE.COLORKA])
plt.title(STORAGE.TITLE_LABEL)
plt.xlabel(STORAGE.X_LABEL)
plt.ylabel(STORAGE.Y_LABEL)
print(STORAGE.PlotActive) # HOW MANY THREADS ACTIVE
if STORAGE.PlotActive == 1:
plt.show()
else:
plt.draw()


class MainWindowApp(App):
pass

if __name__=='__main__':
MainWindowApp().run()
Message has been deleted

Martin Fayad

unread,
Aug 9, 2016, 9:06:27 AM8/9/16
to Kivy users support
NOTE: It seems that if i make the new thread with something else than MatPlotLib graph, it works fine

Bill Janssen

unread,
Aug 14, 2016, 1:39:51 PM8/14/16
to Kivy users support
I tried running this, but it seems to be missing some pieces, particullarly import statements.

Bill

Bill Janssen

unread,
Aug 14, 2016, 1:47:49 PM8/14/16
to Kivy users support
But the problem seems clear:  you can't run the tkinter matplotlib backend in anything other than the main loop.  And I doubt that you can use the Kivy mainloop with the Tk libraries.  You've got to use Tk.mainloop().

Better to try the matplotlib backend from the Kivy Garden.  Even there, though, any code which updates the plot needs to be run on the Kivy main thread.


Bill

On Tuesday, August 9, 2016 at 4:54:58 AM UTC-7, Martin Fayad wrote:

Martin Fayad

unread,
Aug 21, 2016, 6:44:04 AM8/21/16
to Kivy users support
So if I understand it well, the matplotlib window that opens behaves basicly like another gui as it uses tkinter and therefore there are two GUIs running in the same time?

Anyway - I attach the whole folder with the codes

MatplotlibGUI.rar
Reply all
Reply to author
Forward
0 new messages