Problems with using queue in Tkinter application

Icarus asm198 at gmail.com
Sun Jul 5 10:56:26 EDT 2009


On Jul 4, 11:24 am, Peter Otten <__pete... at web.de> wrote:
> 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

You had it Peter.  I tried the "import pydoc pydoc.gui()" in the bug
report you referenced and the same thing described there occurred.
After recompiling tcl/tk with --threads-enabled and replacing the
slackware default packages with those everything is working as I
expected.  Thanks for the help.



More information about the Python-list mailing list