Hi guys, i am very surprised how this simple program can hung python (TCL/TK) . It works fine on a linux system but under windows not . Can anyone explain why and eventually which by pass apply ? If i want to write an aplication with a specialized thread that handles the graphic and that is different than the mainloop what i have to do ? thanks in advance , Francesco . # File: hello1.py from Tkinter import * import os import time import win32ui import threading from Tkinter import * import string import sys import glob import commands import win32api class App: def __init__(self,root ): self.r = root self.w = Toplevel(None, background = "#000053") self.w.geometry("200x200+0+0") self.w.resizable(0,0) self.frame = Frame(self.w,width=100,height=100,background = "#000053") self.frame.pack() self.button = Button(self.frame, text="QUIT", fg="red", command=self.frame.quit) self.button.pack(side=LEFT) self.button = Button(self.frame, text="max", fg="red", command=self.maxi) self.button.pack(side=LEFT) self.hi_there = Button(self.frame, text="min", command=self.mini) self.hi_there.pack(side=LEFT) def mini(self): print "MINI hi there, everyone!" self.r.deiconify() self.w.iconify() print "MINI after hi there, everyone!" def maxi(self): print "MAX hi there, everyone!" self.r.iconify() self.w.deiconify() print "MAX after hi there, everyone!" def grillo(root): print 'grillo ThreadID %x ' % win32api.GetCurrentThreadId() while(1): print 'iconify' time.sleep(2.0) root.mini() print 'deiconify' time.sleep(2.0) root.maxi() root = Tk() root.geometry("20x20") root.resizable(0,0) app = App(root) print 'main ThreadID %x ' % win32api.GetCurrentThreadId() gThread = threading.Thread(target=grillo,args=[app]) gThread.start() print 'main start mainloop %x ' % win32api.GetCurrentThreadId() root.mainloop()
I don't know much about the current state of Tkinter and threads, much less on win32. However, this 2002 article may be relevant to you: http://effbot.org/zone/tkinter-threads.htm This block of comment comes from a relatively recent CVS version of _tkinter.c (parts re-flowed to fit in 80 columns): /* The threading situation is complicated. Tcl is not thread-safe, except when configured with --enable-threads. So we need to use a lock around all uses of Tcl. Previously, the Python interpreter lock was used for this. However, this causes problems when other Python threads need to run while Tcl is blocked waiting for events. To solve this problem, a separate lock for Tcl is introduced. Holding it is incompatible with holding Python's interpreter lock. The following four macros manipulate both locks together. ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made that could call an event handler, or otherwise affect the state of a Tcl interpreter. These assume that the surrounding code has the Python interpreter lock; inside the brackets, the Python interpreter lock has been released and the lock for Tcl has been acquired. Sometimes, it is necessary to have both the Python lock and the Tcl lock. (For example, when transferring data from the Tcl interpreter result to a Python string object.) This can be done by using different macros to close the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl lock. By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event handlers when the handler needs to use Python. Such event handlers are entered while the lock for Tcl is held; the event handler presumably needs to use Python. ENTER_PYTHON releases the lock for Tcl and acquires the Python interpreter lock, restoring the appropriate thread state, and LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between ENTER_PYTHON and LEAVE_PYTHON. These locks expand to several statements and brackets; they should not be used in branches of if statements and the like. If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is only valid in the thread that created it, and all Tk activity must happen in this thread, also. That means that the mainloop must be invoked in the thread that created the interpreter. Invoking commands from other threads is possible; _tkinter will queue an event for the interpreter thread, which will then execute the command and pass back the result. If the main thread is not in the mainloop, and invoking commands causes an exception; if the main loop is running but not processing events, the command invocation will block. In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient anymore, since multiple Tcl interpreters may simultaneously dispatch in different threads. So we use the Tcl TLS API. */ These comments may not apply to your version of Tcl and Tkinter, since they depend on the compile options for Tcl and the Python version. Jeff
participants (2)
-
francesco.grillo@ciaolab.com -
Jeff Epler