GiD - The personal pre and post processor
2. Using Tcl from Python
Here we’ll introduce using Tcl from Python.
Hopefully you’ve got Tcl and Python and Tohil installed and you can follow along and try stuff out.
2.1. tohil.eval
>>> import tohil
>>> tohil.eval('puts "Hello, world."')
Hello, world.
Not bad. You can actually do a lot with that.
Anything the Tcl code returns can be gotten by Python.
>>> t = tohil.eval('return "Hello, world."')
>>> t
<tohil.tclobj: 'Hello, world.'>
>>> str(t)
'Hello, world.'
Here we’ll use Tcl’s clock format function to format a Unix epoch seconds-since-1970 clock into a Posix standard time in the Spanish locale:
>>> clock = 1616182348
>>> tohil.eval(f"clock format {clock} -locale es -gmt 1")
'vie mar 19 19:32:28 GMT 2021'
2.2. helper functions
We can load in Tcl packages by doing
but we do this so often that tohil provides a shortcut:
You can specify the version as an optional argument, either by positional or named parameter. The following two statements are equivalent:
Experienced Python developers without a lot of Tcl experience may be surprised by Tcl’s leniency when it comes to data types.
Here we request a Tcl package with the version number specified as floating point. It works fine.
Another one you’d end up doing a lot is tohil.eval("source file.tcl")
. For that we provide the slightly less paper-cutty…
2.3. tohil.call
You get fancy and start using f-strings to create Tcl commands with arguments, maybe you’re doing something like
If any of those variables being substituted contain dollar signs, quotes, or square brackets, you’re not going to have a good time, because Tcl is going to try to interpret that stuff, and that could lead to errors up to and including remote code execution.
Consequently, Tohil provides tohil.call, a function that takes an arbitrary number of arguments and passes them one-for-one to the corresponding Tcl function in a way that keeps Tcl from trying to interpret any of the arguments.
The key thing in the above is tohil.call('clock', 'format', clock, '-locale', 'fr')
, equivalent to tohil.eval(f"clock format {clock} -locale fr")
but without the risk of inadvertent misinterpretation of arguments.
2.4. tohil.expr
You can also evaluate Tcl expressions from Python using tohil.expr. As with many other tohil functions, to= can be used to request conversion to a specific Python datatype.
2.5. tohil.getvar and tohil.setvar
Python has direct access to Tcl variables and array elements using tohil.getvar. Likewise, tohil.setvar can set them.
As you can see, it’s an error to try to get a variable or array element that doesn’t exist. You can use tohil.exists to see if the variable exists, or trap the Python exception, or make use of tohil.getvar’s handy default keyword-only argument:
2.6. tohil.exists
You can use tohil.exists to see if a variable or array element exists:
2.7. tohil.incr
tohil.incr takes a Tcl variable name or array element and attempts to increment it.
If the contents of the variable preclude it being used as an int, a Python TypeError exception is thrown.
An optional position argument specifies the amount to increment by. The default increment is 1. Negative increments are permitted. The increment amount can also be specified as a keyword argument, using “incr”.
2.8. tohil.unset
tohil.unset can be used to unset variables, array elements, and even entire arrays in the Tcl interpreter.
Unset takes an arbitrary number of arguments, including zero.
Unsetting an array element uses Tcl subscript notation, for example
tohil.unset('x(e)')
.Unsetting an array by name without a subscript will unset the entire array.
It is not an error to attempt to unset a variable that doesn’t exist.
2.9. tohil.subst
Tcl’s subst command is pretty cool. By default it performs Tcl backslash, command and variable substitutions, but doesn’t evaluate the final result, like eval would. So it’s handy for generating some kind of string, but with embedded $-substitution and square bracket evaluation.
2.10. tohil.convert
tohil.convert will convert some Python thing passed to it, into a Tcl object, and then back to some other Python type, any type supported in accordance with the to= argument.
The “to=” way of requesting a type conversion is supported. Although you might not care about converting to int or float or something, you might want a tohil.tclobj for your efforts, anirite?
2.11. tohil.interact
Run the Tcl interactive command loop on stdin, hopefully a terminal, until you send an EOF, at which point you’ll be returned to the Python command line. See also tohil::interact.
THis is handy if you’re using Python interactively and you find yourself making a lot of tohil.eval calls to manipulate the Tcl interpreter, you can flip to the Tcl interpreter, interact with it directly, then flip back by sending an end-of-file.
2.12. tohil.tcl_stdout_to_python()
Redirect Tcl’s standard output to pass through Python’s I/O subsystem.
Among other things, if using Jupyter Notebook, invoking tohil.tcl_stdout_to_python() will cause output from the Tcl interpreter to appear in the notebook.
tclvar
COPYRIGHT © 2022 · GID · CIMNE