将Python变量传递给`Tkinter.Tcl()。eval()`

时间:2014-08-13 14:33:36

标签: python tkinter tcl

我可以提供一个Tcl脚本,并从所述脚本运行proc,如下所示:

import Tkinter
>>> tclsh = Tkinter.Tcl()
>>> tclsh.eval('source {myscript.tcl}')
>>> tclsh.eval('myproc')
...[output of proc]
>>>

但是,如果我想将变量传递给此proc,我必须这样做(假设procdict作为参数:

>>> tclsh.eval('dict set spec num 10000')
>>> tclsh.eval('dict set spec time 10000')
>>> tclsh.eval('dict set spec rate 10')

从Tkinter的上下文中有没有更容易,更Pythonic的方法来做到这一点?我见过variable classes,但它们似乎没有dict风格的变量,甚至根本没有代码的Tcl解释器部分。

1 个答案:

答案 0 :(得分:3)

变量类是一个好主意,但没有特定的dict版本可用,这有点难看,但你可以简单地使用一个字符串版本(并因此而受到性能影响,但那可以修复)

首先是简单的方法。 Tcl dict有一个字符串表示,可以自动转换为它的字符串rep,所以如果你有一个需要dict的proc,你可以直接传入dict的字符串rep,它就可以了。

interp = tkinter.Tcl()
myvar = tkinter.StringVar()

def pydict2tcldict(d):
    return tkinter._stringify(list(d.items()))

d = {'num': 10000, 'time': 10000, 'rate': 10}
myvar.set(pydict2tcldict(d))

interp.eval("""source {myscript.tcl}
               myproc $%s""" % myvar._name)

通过提供一个特殊的dict变量包装而不是通过字符串rep的慢速往返,你当然可以使事情变得更好更快,参见变量类的实现。

但是从根本上说tkinter只是缺少_tkinter.c模块中的一些转换函数(参见AsObj / FromObj / CallArgs),如果添加了适当的映射代码(平凡) ,你可以简单地做到这一点并完成(而且速度相当快):

interp.call("myproc", d)

在阅读Tcl dict C API联机帮助页和Python映射C-API(https://www.tcl.tk/man/tcl8.6/TclLib/DictObj.htmhttps://docs.python.org/2/c-api/mapping.html)后,modules/_tkinter.c的补丁应该非常简单。