Problems with using queue in Tkinter application

Peter Otten __peter__ at web.de
Sat Jul 4 12:24:06 EDT 2009


Icarus wrote:

> On Jul 4, 3:21 am, Peter Otten <__pete... at web.de> wrote:
>> 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 byhttp://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
> 
> Peter, thanks for the suggestion.  I tried your code exactly on my box
> and I still get the same results.  As soon as I run the script and
> every time I click on the Text box I get tcl::Bgerror ... just like I
> mentioned above.  I'm fairly certain that I'm not calling Tkinter
> functions from any other thread but it's acting as though I am as soon
> as I create the input thread.
> If I comment out the input loop thread everything is fine but of
> course that's not terribly useful as a logging box.

http://bugs.python.org/issue3835

Could tcl have been built without thread support on the failing machines?

Peter




More information about the Python-list mailing list