Based on the comments in the source code for the _tkinter module, it looks like tkinter is actually no less designed to be thread safe if Tcl was built with the --enable-threads option. This is confirmed by a resolved error on the Python tracker ( issue11077 ), which states that tkinter is not thread safe, where it was ultimately that all thread safety problems with tkinter were errors that were fixed in Python 2.7.3 +
Here is what the _tkinter module source says about this:
The Tcl interpreter is valid only in the thread that created it, and all Tk actions must also be performed in this thread. This means that mainloop must be called on the thread that the interpreter created. Calls to commands from other threads are possible; _tkinter will queue an event for the interpreter thread, which will then execute the command and return the result. If the main thread is not in mainloop, and the callers throw an exception; if the main loop is started but does not process events, the command call will be blocked.
So, as long as mainloop is actively working in the main thread of the application, tkinter will automatically schedule the method to run in the main thread, which will make it thread safe. However, most Internet sources, in addition to the actual Tkinter source code and the above error report, indicate that using tkinter with streams is crashing. I'm not quite sure what to believe, although in some small examples I tried, updating the GUI from the stream worked fine.
Now you were wondering if the thread safety rules associated with Tk widgets apply to Variable subclasses. He: Here are some of the implementations of Variable , the parent element of IntVar :
class Variable: _default = "" _tk = None def __init__(self, master=None, value=None, name=None): """Construct a variable MASTER can be given as master widget. VALUE is an optional value (defaults to "") NAME is an optional Tcl name (defaults to PY_VARnum). If NAME matches an existing variable and VALUE is omitted then the existing value is retained. """
When you set variable, it calls the globalsetvar method of the main widget associated with Variable . The _tk.globalsetvar method _tk.globalsetvar implemented in C and internally calls var_invoke , which internally calls WaitForMainLoop , which will try to schedule the command to execute on the main thread, as described in the quote from the _tkinter source included above.
static PyObject* var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags) { if (!WaitForMainloop(self)) return NULL; static PyObject * Tkapp_GlobalSetVar(PyObject *self, PyObject *args) { return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY); }
Note that this code path is also used for get operations, so set and get operations are defined by the same rules.