Icarus wrote: > I'm working on a serial protocol analyzer in python. We have an > application written by someone else in MFC but we need something that > is cross platform. I intended to implement the GUI portion in Tkinter > but am having trouble. > > The idea is that I will read messages from the serial port and output > them to a Tkinter Text object initially. Eventually it will have > other functionality but that's it for the short term. I've written > this little test app to experiment with putting things on the GUI via > a Queue which is polled by the Tkinter loop. > > On some machines this code works fine and I get whatever I type in > displayed in the Text widget. On others I get errors like this as > soon as I start it running. > > error in background error handler: > out of stack space (infinite loop?) > while executing > "::tcl::Bgerror {out of stack space (infinite loop?)} {-code 1 -level > 0 -errorcode NONE -errorinfo {out of stack space (infinite loop?) > while execu..." > > > I don't understand why on some machines it works exactly as expected > and on others it acts the same way Tkinter does when I call functions > directly from outside the Tkinter thread. Does anyone have any > suggestions? The full code as appended below. Thanks in advance. > > [code] > > import Queue > > class functionQueue: > > def __init__(self, root = None, timeout = 250): > > self.functionQueue = Queue.Queue() > self.root = root > self.timeout = timeout > > if(self.root): > self.pop_function(root) > > > def pop_function(self, root = None): > > try: > funcArgList = self.functionQueue.get(block = False) > except Queue.Empty: > pass > else: > try: > funcArgList[0](*funcArgList[1]) > except: > try: > print "Failed to call function", funcArgList[0] > except: > print "Failed to call function" > > if(root): > root.after(self.timeout, lambda: self.pop_function > (self.root)) > > def add_function(self, function, argList): > > try: > self.functionQueue.put([function, argList]) > except: > pass > > > if( __name__ == '__main__'): > > import Tkinter > import thread > > text = Tkinter.Text() > text.pack() > > myQueue = functionQueue(text, 50) > > def gui_loop(): > try: > text.mainloop() > except: > import os > os._exit(1) > > thread.start_new_thread(text.mainloop, ()) > > while(True): > usrInput = raw_input() > > if(usrInput == "-1"): > import os > os._exit(0) > > myQueue.add_function(text.insert, ['end', usrInput + "\n"]) > myQueue.add_function(text.see, ['end']) > > [/code]
I can make it work over here by putting the UI into the main thread, as suggested by http://effbot.org/zone/tkinter-threads.htm: import Queue import Tkinter import threading class FunctionQueue: # unchanged def input_loop(): while True: try: usrInput = raw_input() except EOFError: break myQueue.add_function(text.insert, ['end', usrInput + "\n"]) myQueue.add_function(text.see, ['end']) myQueue.add_function(text.quit, []) if __name__ == '__main__': text = Tkinter.Text() text.pack() myQueue = FunctionQueue(text, 50) threading.Thread(target=input_loop).start() text.mainloop() Peter -- http://mail.python.org/mailman/listinfo/python-list