By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,186 Members | 1,620 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,186 IT Pros & Developers. It's quick & easy.

Crashing Python.exe with TkInter

P: n/a

I've run into a problem with Python/TkInter crashing, with an
attempt to read illegal addresses, on Win on Win2000 and WinXP.

With some web-searching, I found that people say not to
manipulate TkInter from multiple threads, except that the call
event_generate() is safe. I assume the call adds an event to
Tk's queue, and later the thread running mainloop will() pick up
the event.

I tried to write a general-purpose thread-runner. In the code
below, 'thread-it' runs a given function in a new thread, saves
the result, and triggers event_generate(). When the mainloop
handles the event, it calls a second given function with the
saved result.

The code below *seems* to work. It requires only the current
Python distribution. To make it usually crash, un-comment the
'print' statement in add_to_listbox(). That's all.

With no prints, it works. Adding prints in various places
causes it usually to crash with an unreadable-memory error from
the OS. I get the same behavior on the command-line and in
Idle. Occasionally, it prints something like:

TclExecuteByteCode: abnormal return at pc 45: stack top 39 < entry
stack top 59
TclExecuteByteCode execution failure: end stack top < start stack top

which is usually also accompanied by the read addressing error.

I'm sure I've previously been able to print from multiple Python
threads. Can anyone tell what is going on?

from Tkinter import *
import thread
import time

class Application(Frame):

def __init__(self):
Frame.__init__(self, None)
self.event_name_cntr = 0
self.pack()
self.listbox = Listbox(self)
self.listbox.pack(side=TOP)

def add_to_listbox(self, msg):
self.listbox.insert(END, msg)
# print "Adding", msg

def thread_it(self, finish_func, asyc_func, args=()):
""" Create a thread that calls asyc_func(*args), then trigger
an even with event_generate(). When the event loop handles
the event, call finish_func with the return value of asyc_func.
"""
event_name = "<<j7A5x0VjqZ3b_%x>>" % self.event_name_cntr
self.event_name_cntr += 1
result = [None]
def _on_finish(_):
self.unbind(event_name)
finish_func(result[0])
def do():
result[0] = asyc_func(*args)
self.event_generate(event_name)
self.bind(event_name, _on_finish)
thread.start_new_thread(do, ())

app = Application()

def fin(s):
""" When the async function returns, we'll add its output
to the list box.
"""
app.add_to_listbox(s)

def async(n):
""" In the threads, we'll just sleep then return a string.
"""
time.sleep(2.0)
return "Got %d asyncronously." % n

for i in range(5):
# Run a few threads
app.thread_it(fin, async, [i])

app.mainloop()

Thanks,
--
--Bryan
Jul 18 '05 #1
Share this question for a faster answer!
Share on Google+

This discussion thread is closed

Replies have been disabled for this discussion.