启动tclsh并输入:
close [open "|tclsh" w]
它工作正常。
但是,当~/.tclshrc
中有package require Tk
时,同一行会使tclsh变为HANG!
同样的问题是所有的GUI软件包,如Tk,Itk,Img,Iwidgets,但是如果没有像Itcl这样的GUI软件包,它就会很糟糕。
如何解决此问题?关键是在tclsh
中使用close [open "|tclsh" w]
键入package require Tk
时,~/.tclshrc
不要挂起。
同样的问题是wish
。 close [open "|wish" w]
希望HANG(带有~/.wishrc
个空文件)!
我在32位和64位CentOS上都遇到了这个问题。 我有以下版本的软件包:tcl-8.5.8,tk-8.5.8,img-1.3,itcl-3.4.b1,itk-3.3,iwidgets-4.0.1。
答案 0 :(得分:2)
Tcl应用程序主要在完成脚本时退出,无论是否以交互方式提供。然而,Tk包改变了一些东西,以便在到达脚本结束时,它转而进入循环处理事件。如果你依赖于文件结尾导致事情退出,这看起来很像挂起,但实际上它只是等待GUI应用程序完成(因此它可以报告子进程的退出状态) )。
修复方法是在子进程中为stdin
创建一个通道可读的事件处理程序。有几种方法可以详细地做到这一点,但这里有一个简单的方法可以放在你通常发送的大量代码的末尾:
proc ReadFromStdin {} {
if {[gets stdin line] >= 0} {
uplevel "#0" $line
} elseif {[eof stdin]} {
exit
} else {
# Partial read; try later when rest of data available
}
}
fileevent stdin readable ReadFromStdin
这假定每一行都是完整的可执行命令;当然,这可能不是真的,但编写使用info complete
来组成行的代码不太清楚,在这里可能是不必要的。 (你知道你实际发送的东西比我更好......)
答案 1 :(得分:1)
我的想法是,它正在等待希望完成运行,按照手册页:
如果channelId是阻止通道 命令管道然后关闭等待 为子进程完成。
由于wish进入无限循环(事件循环)并且永不退出,因此close命令将挂起。沿着同样的路线,[package require Tk](我相信)启动事件循环,因此会导致相同的行为。
我承认,虽然它正在加载.tclshrc,因为
如果在用户的主目录中存在文件.tclshrc(或Windows平台上的tclshrc.tcl),则交互式tclsh会在从标准输入读取第一个命令之前将该文件评估为Tcl脚本。
对我来说,[open“| tclsh”w]在交互式shell中结束似乎很奇怪。
作为旁注,[pacakge require Tk]在.tclshrc中看起来真的很奇怪。理论上,在运行Tcl(即仅命令行应用程序)时,您不会总是想要Tk(窗口和事件循环)......而且,当您确实需要它时,您就知道了。我想,对于他们自己来说,这对我来说似乎很奇怪。