views:

261

answers:

1

Hi

I have the following python code...

import Tkinter

root = Tkinter.Tk()

root.tk.eval('puts {printed by tcl}')

It prints "printed by tcl" to the screen. How can I capture what the tcl interpreter prints to the screen into a python string.

This is a simplified example of what I am doing. I have an automation system written in python but a new piece of equipment that is controlled by a tcl api. Each tcl command prints things like "connected" or "connection failed", I need to be able to capture these into python strings, so the automation system can tell what is going on, so for example if the device does not connect the automation system can retry the connection command.

Cheers

From Nick

+3  A: 

If the code you are running prints to screen and you're calling it with root.tk.eval() you can't capture that. However, You can redefine what "puts" does in the tcl code and have it do whatever you want. This is part of the beauty of Tcl -- there are no reserved words.

Simply create a proc named "puts" in the tcl interpreter, though make sure it has the exact same interface (ie: respects "-nonewline", can write to files, etc). When the puts normally prints to the screen you can instead have it do whatever you want, such as write to a socket or merely return the string it's supposed to print.

Roughly (untested, and ignoring the case with -nonewline):

root.tk.eval('''
rename puts original_puts 
proc puts {args} {
    if {[llength $args] == 1} {
        return "=> [lindex $args 0]"
    } else {
        eval original_puts $args
    }
}
''')

foo = root.tk.eval('puts "hello, world"')
print foo
=> hello, world

It will require a little diligence to make sure you don't break the tcl code which expects a standard "puts" statement, but it's not that hard to do. Just make sure you have special cases for one argument, the first argument of "-nonewline", and where there are two arguments (file descriptor and string).

It might get complicated if you call eval and it does two puts statements, or does a puts and then some other code, since the result of the eval is the result of the last statement. However, you can work around that by having puts buffer its output to a global variable and then return the result of that variable each time you do an eval.

So, think outside the box a little and you can find a solution. Tcl is very flexible.

Bryan Oakley
Thanks for the reply, I think I need to learn more TCL, I mainly know python. Your anwer solves my problem. Thanks.
Luckily, Tcl is amazingly easy to learn. A person can easily get to the point where they can write useful code in it in a day or so.
RHSeeger
nice answer Bryan
glenn jackman