Multithreaded tkinter GUI application exception handling

M

Michael Zhang

My project uses Python-2.3.4 + Tkinter + PIL-1.1.4 to retrieve images
from server and display those images.

I created a thread (also a separate toplevel window) for displaying
images and another thread for recording the frame rates (using a
progress bar for visulization). The whole application worked very well
once it received image data from the socket.

The problem is when I tried to close that display window (click on the
standard "X" button on the right-upper corner), I got this exception:

--------
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/local/lib/python2.3/threading.py", line 436, in __bootstrap
self.run()
File "realtime.py", line 188, in run
UI(self.master)
File "realtime.py", line 238, in __init__
self.canvas.create_image(0, 0, image=self.image, anchor=NW)
File "/usr/local/lib/python2.3/lib-tk/Tkinter.py", line 2060, in
create_image
return self._create('image', args, kw)
File "/usr/local/lib/python2.3/lib-tk/Tkinter.py", line 2049, in _create
return getint(self.tk.call(
TclError: invalid command name ".1080883980.1080884908"
---------

Then after I closed the main windows, I got another exception:

---------
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/local/lib/python2.3/threading.py", line 436, in __bootstrap
self.run()
File "realtime.py", line 198, in run
self.bar.updateProgress(i)
File "/home/michael/usyd/soft3700/py/realtime/progressbar.py", line
73, in updateProgress
self.update()
File "/home/michael/usyd/soft3700/py/realtime/progressbar.py", line
91, in update
float(value) / self.max * self.width, self.height)
File "/usr/local/lib/python2.3/lib-tk/Tkinter.py", line 2039, in coords
self.tk.splitlist(
TclError: invalid command name
".1080881420.connectionPane.1080883148.1080883340"
---------

Why is the "TclError"? How can I handle those exceptions and exit the
applicaton gracefully?

Could someone help me out about those thread stuff? Thanks!

Michael
 
O

Oleg Paraschenko

Hello Michael,

Michael Zhang said:
The problem is when I tried to close that display window (click on the
standard "X" button on the right-upper corner), I got this exception:


Could someone help me out about those thread stuff? Thanks!

I also had the same exception, but I can't remember what was the
reason. You can look at my working code, maybe it can help:

http://uucode.com/texts/pylongopgui/pyguiapp.html
A complete Python Tkinter application demonstrates one of the ways to
implement a good GUI wrapper for a long operation: with a progress
bar, log messages, cancelling.
 
E

Eric Brunel

Michael said:
My project uses Python-2.3.4 + Tkinter + PIL-1.1.4 to retrieve images
from server and display those images.

I created a thread (also a separate toplevel window) for displaying
images and another thread for recording the frame rates (using a
progress bar for visulization). The whole application worked very well
once it received image data from the socket.

The problem is when I tried to close that display window (click on the
standard "X" button on the right-upper corner), I got this exception:

--------
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/local/lib/python2.3/threading.py", line 436, in __bootstrap
self.run()
File "realtime.py", line 188, in run
UI(self.master)
File "realtime.py", line 238, in __init__
self.canvas.create_image(0, 0, image=self.image, anchor=NW)
File "/usr/local/lib/python2.3/lib-tk/Tkinter.py", line 2060, in
create_image
return self._create('image', args, kw)
File "/usr/local/lib/python2.3/lib-tk/Tkinter.py", line 2049, in _create
return getint(self.tk.call(
TclError: invalid command name ".1080883980.1080884908"
---------

Not knowing your application exactly, I can only guess what's happening: it
seems that your secondary thread is not aware that the window is closed and it
still tries to draw things in a canvas that has already been destroyed (module
realtime.py, line 238, according to the traceback).

So you should either make sure your secondary thread is stopped before the
window is closed, or enclose the canvas.create_image in a try except handling
the TclError. This last solution is far from optimal, since any mistake in a
Tkinter call always raises a TclError, so you may catch other errors as well.
I'd go for the first, using for example an Event (in module threading) to
indicate the window is closed.
Then after I closed the main windows, I got another exception:

---------
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/local/lib/python2.3/threading.py", line 436, in __bootstrap
self.run()
File "realtime.py", line 198, in run
self.bar.updateProgress(i)
File "/home/michael/usyd/soft3700/py/realtime/progressbar.py", line
73, in updateProgress
self.update()
File "/home/michael/usyd/soft3700/py/realtime/progressbar.py", line
91, in update
float(value) / self.max * self.width, self.height)
File "/usr/local/lib/python2.3/lib-tk/Tkinter.py", line 2039, in coords
self.tk.splitlist(
TclError: invalid command name
".1080881420.connectionPane.1080883148.1080883340"

Same problem here, this time for the progress bar apparently: you try to do
things in a widget that is already destroyed.

BTW, mixing Tkinter calls in several threads is not a good idea: Tkinter is not
thread-safe and I experienced quite a lot of crashes when trying to do that. The
best solution I could find was to handle all the GUI stuff in the main thread
and make the secondary threads post events in Tkinter's event queue via the
event_generate method to serialize things at GUI level. I'm quite surprised to
hear that you succeeded in making things work, but be aware that you may
experience weird crashes in the future...
Could someone help me out about those thread stuff? Thanks!

Michael

HTH
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top