【问题标题】:Using Python functions in Tkinter.Tcl()在 Tkinter.Tcl() 中使用 Python 函数
【发布时间】:2011-02-11 17:09:04
【问题描述】:
  1. 我有一堆 Python 函数。我们称它们为foobarbaz。它们接受可变数量的字符串参数并执行其他复杂的操作(例如访问网络)。

  2. 我希望“用户”(假设他只熟悉 Tcl)使用这些函数在 Tcl 中编写脚本。

这是用户可以提出的示例(取自Macports):

post-configure {
    if {[variant_isset universal]} {
        set conflags ""
        foreach arch ${configure.universal_archs} {
            if {${arch} == "i386"} {append conflags "x86 "} else {
                if {${arch} == "ppc64"} {append conflags "ppc_64 "} else {
                    append conflags ${arch} " "
                }
            }
        }

        set profiles [exec find ${worksrcpath} -name "*.pro"]
        foreach profile ${profiles} {
            reinplace -E "s|^(CONFIG\[ \\t].*)|\\1 ${conflags}|" ${profile}

            # Cures an isolated case
            system "cd ${worksrcpath}/designer && \
                    ${qt_dir}/bin/qmake -spec ${qt_dir}/mkspecs/macx-g++ -macx \
                    -o Makefile python.pro"
        }
    }
}

这里,variant_isssetreinplace 等等(Tcl 内置函数除外)被实现为 Python 函数。 ifforeachset 等是普通的 Tcl 构造。 post-configure 是一个 Python 函数,它接受一个可以稍后执行的 Tcl 代码块(这显然最终会调用上述 Python“函数”)。

这可以在 Python 中实现吗?如果有,怎么做?

from Tkinter import *; root= Tk(); root.tk.eval('puts [array get tcl_platform]') 是我所知道的唯一集成,显然非常有限(更不用说它在 mac 上启动 X11 服务器的事实)。

【问题讨论】:

  • 并非所有 Tk 版本都在 OSX 上启动 X11。改用该库的 Carbon(或 Cocoa)目标构建...
  • @Donal,重点是 - 它会打开一些 GUI 窗口。如果不是 X11,我会在 Dock 中看到一个跳跃的 Python 火箭图标,然后是一个标题为“tk”的窗口。这对于与 GUI 无关的应用程序来说是不希望的。
  • 我怀疑这可能会发生。毕竟没有声称这是一个答案。
  • 你可以像这样在不加载 Tk 的情况下使用 tcl 解释器: import Tkinter tcl = Tkinter.Tcl() result = tcl.eval(''' puts hello, world ''')

标签: python integration tcl dsl


【解决方案1】:

通过一些实验,我发现你可以做这样的事情来创建一个 tcl 解释器,注册一个 python 命令,并从 Tcl 调用它:

import Tkinter

# create the tcl interpreter
tcl = Tkinter.Tcl()

# define a python function
def pycommand(*args):
    print "pycommand args:", ", ".join(args)

# register it as a tcl command:
tcl_command_name = "pycommand"
python_function = pycommand
cmd = tcl.createcommand(tcl_command_name, python_function)

# call it, and print the results:
result = tcl.eval("pycommand one two three")
print "tcl result:", result

当我运行上面的代码时,我得到:

$ python2.5 /tmp/example.py
pycommand args: one, two, three
tcl result: None

【讨论】:

  • 太棒了!此外 - pycommand 的参数和返回值恰好都是字符串,这很明显,因为 Tcl 将值表示为字符串。如果您返回一个列表 ([1, "foo"]),例如,从 pycommand ... 当 tcl.eval 返回时将转换为字符串。您的示例中打印的“无”实际上是字符串类型(如type(result) 所示)。
  • 我刚刚意识到,作为纯字符串传递给 Python 函数的代码块 ({...}) 可以简单地再次 evaled。
  • tcl.setvar 可用于填充 Tcl 代码要使用的变量.. 虽然我不知道如何传递虚线值 (${configure.universal_archs})。
  • 很容易,点在 Tcl 变量名中并不特别(它只对 $ 求值很特殊,但对 [set] 没有)。
【解决方案2】:

@Brian - 我必须进行试验才能得到正确的结果

from Tkinter import Tcl
tcl = Tcl()
result = tcl.eval(' puts "hello, world" ')

注意单引号和双引号的位置。这给了我预期的输出:你好,世界

单引号或双引号的任何其他组合都会导致以下回溯:

  File "<stdin>", line 1, in <module>
_tkinter.TclError: can not find channel named "hello,"

--- fracjackmac

【讨论】:

  • 你想表达什么观点?如果你给出无效的 Tcl 代码你会得到一个错误,或者你是在问为什么你会得到那个错误?
猜你喜欢
  • 1970-01-01
  • 2012-10-28
  • 1970-01-01
  • 1970-01-01
  • 2019-05-03
  • 2019-06-06
  • 2017-02-27
  • 2018-04-23
相关资源
最近更新 更多