如何在使用tkinter时将tcl的stdout获取到Python字符串变量中?
我有以下的python代码...
import Tkinter
root = Tkinter.Tk()
root.tk.eval('puts {printed by tcl}')
这段代码会在屏幕上打印“printed by tcl”。我想知道怎么才能把tcl解释器打印到屏幕上的内容捕捉到一个python字符串里。
这是我正在做的一个简化示例。我有一个用python写的自动化系统,但有一台新设备是通过tcl的接口来控制的。每个tcl命令都会打印一些信息,比如“已连接”或者“连接失败”。我需要把这些信息捕捉到python字符串里,这样自动化系统才能知道发生了什么。例如,如果设备没有连接,自动化系统就可以重新尝试连接命令。
谢谢
来自Nick
1 个回答
如果你运行的代码是直接在屏幕上打印内容,并且你是通过 root.tk.eval() 来调用它的,那么你是无法捕捉到这些输出的。不过,你可以在 tcl 代码中重新定义 "puts" 这个命令,让它做你想要的事情。这就是 Tcl 的一个优点——没有保留字。
你只需要在 tcl 解释器中创建一个叫 "puts" 的过程,但要确保它的功能和原来的 "puts" 一模一样(比如要支持 "-nonewline" 参数,能够写入文件等等)。当 puts 通常在屏幕上打印内容时,你可以让它做其他事情,比如写入一个套接字,或者仅仅返回它应该打印的字符串。
大致上(未经测试,且不考虑 -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
你需要稍微用点心,确保不会破坏那些期望标准 "puts" 语句的 tcl 代码,但这并不难。只要确保处理好一个参数的情况、"-nonewline" 的第一个参数,以及两个参数的情况(文件描述符和字符串)。
如果你调用 eval 并且它执行了两个 puts 语句,或者先执行一个 puts 然后执行其他代码,可能会有点复杂,因为 eval 的结果是最后一个语句的结果。不过,你可以通过让 puts 将输出缓存在一个全局变量中,然后每次执行 eval 时返回这个变量的结果来解决这个问题。
所以,稍微跳出框框思考一下,你就能找到解决方案。Tcl 是非常灵活的。