Easy multithreading with Tkinter
Easy multithreading with Tkinter on CPython 2.7/3.x and PyPy 2.7/3.x.
The Tcl/Tk language that comes with Python follows a different threading model than Python itself which can raise obtuse errors when mixing Python threads with Tkinter, such as:
RuntimeError: main thread is not in main loop RuntimeError: Calling Tcl from different apartment NotImplementedError: Call from another thread
Tcl can have many isolated interpreters, and each are tagged to the its particular OS thread when created. Python's _tkinter module checks if the calling Python thread is different than the Tcl/Tk thread, and if so, waits one second for the Tcl/Tk main loop to begin dispatching. If there is a timeout, a RuntimeError is raised. On PyPy, a NotImplementedError is raised.
For non-Tk calls into Tcl, Python will raise an apartment RuntimeError when calling a Tcl interpreter from a different thread.
The approach used in
tkthread is to use the Tcl/Tk
messaging to notify the Tcl/Tk main loop of a call for execution.
This interrupt-style architecture has lower latency and better
CPU utilization than periodic polling.
tkthread module provides the
TkThread class, which can
synchronously interact with the main thread.
from tkthread import tk, TkThread root = tk.Tk() # create the root window tkt = TkThread(root) # make the thread-safe callable import threading, time def run(func): threading.Thread(target=func).start() run(lambda: root.wm_title('FAILURE')) run(lambda: tkt(root.wm_title,'SUCCESS')) root.update() time.sleep(2) # _tkinter.c:WaitForMainloop fails root.mainloop()
tkt instance is callable, and will wait for the Tcl/Tk main loop
to execute and compute a result which is then passed back for
return in the calling thread. A non-synchronous version also exists that
does not block:
tkt.nosync(root.wm_title, 'ALSO SUCCESS')
There is an optional
tkt.install() method which intercepts Python-to-Tk
calls. This must be called on the default root, before the creation of child
widgets. If installed, then wrapping Tk widget calls in threaded code with
tkt is not necessary. There is, however, a slight performance penalty for
Tkinter widgets that operate only on the main thread because of the
root Tcl/Tk interpreter must be the primary interpreter on the
main thread. If it is not, then you will receive a TclError of the form:
_tkinter.TclError: invalid command name "140520536224520_call_from"
For example, creating several
Tk() instances and then using TkThread
on those will cause this error.
A good practice is to create a root window and then call
to keep the primary Tcl/Tk interpreter active. Future Toplevel windows
root as the master.
pip install tkthread
Licensed under the Apache License, Version 2.0 (the "License")
These libraries offer similar functionality, using periodic polling:
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
|Filename, size||File type||Python version||Upload date||Hashes|
|Filename, size tkthread-0.3.0.zip (14.4 kB)||File type Source||Python version None||Upload date||Hashes View hashes|