Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从Python运行TCL代码(在现有TCL shell上)_Python_Shell_Tkinter_Tcl - Fatal编程技术网

从Python运行TCL代码(在现有TCL shell上)

从Python运行TCL代码(在现有TCL shell上),python,shell,tkinter,tcl,Python,Shell,Tkinter,Tcl,导言 我最近开始在Linux下开发一个遗留产品,它包含一个内置的TCL shell。由于公司的限制,我无法控制“幕后”,我能写的所有代码都必须在这个TCL外壳下运行,处理产品预定义的笨拙的TCL API 我曾几次想知道是否有可能将一些Python补丁到这个设置中,因为有些解决方案在Python中似乎比在TCL中更合法。通过修补Python,我的意思是:要么从TCL代码本身调用Python代码(例如,可以使用Elmer完成),要么从产品外部使用Python包装TCL API(我没有找到“经典”解决

导言

我最近开始在Linux下开发一个遗留产品,它包含一个内置的TCL shell。由于公司的限制,我无法控制“幕后”,我能写的所有代码都必须在这个TCL外壳下运行,处理产品预定义的笨拙的TCL API

我曾几次想知道是否有可能将一些Python补丁到这个设置中,因为有些解决方案在Python中似乎比在TCL中更合法。通过修补Python,我的意思是:要么从TCL代码本身调用Python代码(例如,可以使用Elmer完成),要么从产品外部使用Python包装TCL API(我没有找到“经典”解决方案)

问题

考虑到产品中已有一个现有的TCL外壳,我浏览过的大多数解决方案(例如Tkinter)都不能用于从Python运行TCL代码。我需要将代码“注入”到现有的shell中

考虑的解决方案

作为一个解决方案,我考虑在TCL端启动一个简单的服务器,它运行从Python端接收的简单命令。我写了一个小演示,效果很好。这使我能够用Python为笨拙的TCLAPI编写一个漂亮的、基于类的包装器,还可以管理命令队列等等

我想到的另外两个解决方案是将软件从Python中分离出来,使用读/写文件描述符,或者通过FIFO而不是套接字进行连接

然而,我想知道我是否真的做对了,或者你能提出一个更好的解决方案吗

提前感谢。

首先: 如果您只需要一个基于类的OO系统来编写代码,您不需要python,Tcl可以很好地实现OO。(内置于8.6中,但在较旧的版本中,也有相当多的选项可以获得OO特性、类等,例如Tcllibs或

如果您仍然认为Python是手头任务的最佳工具(例如,由于某些任务的库支持更好),您可以使用Tcllib comm包“远程控制”Tcl解释器。这需要在您想要控制的Tcl shell中有一个工作事件循环,但除此之外,这是非常简单的

在Tcl shell中,安装Tcllib comm包。 (如果需要帮助,请再次询问)

一旦你有了它,在你的Tcl外壳中启动comm服务器

package require comm
set id [::comm::comm self]
# write ID to a file
set fd [open idfile.txt w]
puts $fd $id
close $fd
proc stop_server {} {set ::forever 1 }
# enter the event loop
vwait forever
在python方面,您的做法几乎相同,只是在Tkinter代码中

基本上是这样的:

import Tkinter
interp = Tkinter.Tcl()
interp.eval('package require comm')

# load the id
with open('idfile.txt') as fd:
    comm_id = fd.read().strip()

result = interp.eval(
    'comm::comm send {0!s} {1!s}'.format(comm_id, '{puts "Hello World"}')
使用该python代码和shell,您应该可以在shell中看到打印的
helloworld

阅读通信手册了解更多详细信息,如何确保安全,获取回调等

如果您不喜欢tkinter负担,您也可以实现comm的wire procotol,在Twisted中不应该太难,或者在Python3.x中使用新的异步支持。 在线协议记录在:

。关键是不需要知道有一个java子进程参与。套接字比管道更强大,更可移植(即使在Windows上,套接字也可以使用
select()
)虽然管道在某些情况下可能更简单。如果您拥有的Tcl shell支持偶数循环,您可以简单地使用Tcllib comm包将python
tkinter.Tcl()
解释器与Tcl shell连接,并通过TCP/IP发送命令。然后,只需将tkinter包装器包装在python代码中即可。(请参阅,如果您愿意,wire协议也有文档记录)谢谢!第一行(
设置srv[::comm:comm]
)是否有错误,因为
::comm::comm
需要一个参数,而您没有真正使用
srv
,或者我遗漏了什么?