What is a mechanism equivalent to "trace variable w ..." in Tcl for Python?
Terry Reedy
tjreedy at udel.edu
Fri Sep 30 21:17:55 EDT 2016
On 9/30/2016 2:23 PM, Les Cargill wrote:
>
> A really interesting design approach in Tcl is to install a callback
> when a variable is written to. This affords highly event-driven
> programming.
>
> Example ( sorry; it's Tcl ) :
>
>
> namespace eval events {
> set preRPM -1
> proc handleRPM { args } {
> # do stuff to handle an RPM change here
> variable ::motor::RPM
> variable preRPM
> puts "RPM changed from $preRPM to $RPM
> set preRPM $RPM
> }
> }
>
> ...
>
> trace variable ::motor::RPM w ::events::handleRPM
'trace variable' and the corresponding 'trace vdelete' and trace vinfo'
have been deprecated in favor of the newer 'trace add variable', 'trace
remove variable', and 'trace info variable. In 3.6, the tkinter
Variable class has corresponding new trace_add, trace_remove, and
trace_info methods.
> ...
>
> set ::motor::RPM 33.33
The cost of being able to trace variables is having to set them through
a method that can check for the existence of callbacks. The are used in
tk to connect the values of widgets.
> What is an equivalent mechanism in Python?
Python has a trace module for functions and lines, rather than
variables. I believe the primary intended use is for debugging.
The Variable class in tkinter.__init__, currently about line 290, wraps
the tcl mechanism so it literally is the 'equivalent mechanism' in
Python. It could be rewritten to do everything in Python instead of
calling into tk. However, it can also be used as it without displaying
a gui window. Use what you already know.
import tkinter as tk
root = tk.Tk() # Only needed to create Vars.
root.withdraw() # So keep it invisible.
avar = tk.StringVar(root)
avar.trace_add('write', lambda tk_id, unknown, mode:
print(avar.get(), tk_id, unknown, mode))
# See >>> help(tk.Variable.trace_add) for more.
avar.set('abc')
avar.set('def')
* prints
abc PY_VAR0 write # 'unknown' == ''
def PY_VAR0 write
Since you are familiar with tcl, you could potentially use root.call()
to call into tcl yourself.
There are other packages in Python that implement the idea of
broadcasting a change to a set of reistered listeners.
--
Terry Jan Reedy
More information about the Python-list
mailing list