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