如何使用 Tcl 的(interp)bgerror
我正在尝试 在从属解释器中运行 tclhttpd 但稍作修改以便在 tclkit 中运行。下面的代码“运行”(我可以点击 http://localhost:8015 ),但永远不会到达 put 行底部因为“服务器没有返回,它进入[vwait Forever]”。但是当我尝试“after 0 技巧”时,例如在“$httpd eval $cmd”行前面添加“after 0”,服务器根本不运行,所以我认为“错误必须由 bgerror 处理”
但是我找不到如何使用 bgerror 的好例子,而且我的研究表明,现在的惯例是使用“interp bgerror”。请参阅 http://www2.tcl.tk/_ 返回的前几个示例/gsearch?S=bgerror;第一个链接包含措辞“填写使用 bgerror 的有用技巧和示例”,但没有我可以辨别如何应用的示例,第二个链接的结论是“我对如何使用它的示例感兴趣”。
package require starkit
starkit::startup
set httpd_args [list]
set httpd [interp create]
$httpd eval "set argc [llength $httpd_args]"
set cmdargv "set argv [list $httpd_args ]"
$httpd eval "set topdir $starkit::topdir"
$httpd eval $cmdargv
set cmd [list source [file join $starkit::topdir bin/httpd.tcl]]
$httpd eval $cmd
puts "if seeing this controlled has returned"
I'm trying to run tclhttpd in a slave interpreter but slightly modified so as to run within a tclkit. The code below "runs" (I can hit http://localhost:8015) but never reaches the puts line at the bottom because "the server does not return, it enters [vwait forever]". But when I try "the after 0 trick", e.g. prepending "after 0 " to the line "$httpd eval $cmd", the server does not run at all, so I presume "errors have to be handled by bgerror"
However I cannot find good examples of how to use bgerror, plus my research shows that now the convention is to use "interp bgerror". Please see the first couple of examples returned by http://www2.tcl.tk/_/gsearch?S=bgerror; the first link contains the verbiage "fill in useful tricks and examples for using bgerror" but then there are no samples I can discern how to apply, and the second link concludes "I am interested in examples how this is supposed to be used."
package require starkit
starkit::startup
set httpd_args [list]
set httpd [interp create]
$httpd eval "set argc [llength $httpd_args]"
set cmdargv "set argv [list $httpd_args ]"
$httpd eval "set topdir $starkit::topdir"
$httpd eval $cmdargv
set cmd [list source [file join $starkit::topdir bin/httpd.tcl]]
$httpd eval $cmd
puts "if seeing this controlled has returned"
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我不太明白你问的问题。听起来你的目标是在一个解释器中启动一个 http 服务器,但以某种方式与主解释器交互。是这样吗?如果是这样,那与 bgerror 有什么关系?
您是否知道,即使您在单独的解释器中运行服务器,它也不是在单独的线程中运行?也就是说,当任一解释器被 vwait 阻止时,您无法 (*) 与主解释器交互。
(*) 你可以,如果你的交互采用 Tk 小部件的形式,并且也利用事件循环
至于如何使用 bgerror,有几种工作方式。默认机制调用函数“bgerror”,您可以定义该函数来执行您想要的任何操作。它需要一个字符串(错误消息的文本)并对其执行某些操作。该某事可能是将错误打印到 stdout、在对话框中显示、将其写入文件等。
作为示例,请考虑此交互式会话:
您还可以注册自己的错误处理程序,如“interp bgerror”文档中所述。出现在 tcl 8.5 中,尽管它有一个 bug 直到 8.5.3 才修复。
例如:
这有助于回答您的问题吗?
I don't quite understand the question you are asking. It sounds like your goal is to start up an http server in one interpreter but somehow interact with the main interpreter. Is that right? If so, what does that have to do with bgerror?
Are you aware that even though you are running the server in a separate interpreter, it is not running in a separate thread? That is, you can't (*) interact with the main interpreter while either interpreter is blocked by a vwait.
(*) you can, if your interaction takes the form of Tk widgets that also take advantage of the event loop
As for how to use bgerror, There are a couple of ways that it works. The default mechanism calls the function 'bgerror" which you may define to do whatever you want. It takes a single string (the text of an error message) and does something with it. That something could be to print the error to stdout, show it in a dialog, write it to a file, etc.
As an example, consider this interactive session:
You can also register your own error handler, as described in the documentation for "interp bgerror". This came along in tcl 8.5, though it had a bug that wasn't fixed until 8.5.3.
For example:
Does this help answer your question?
根据OP的评论完全编辑...
after 0技巧是以下行:
它的作用是告诉interp将有问题的命令($http eval $cmd)添加到事件队列,这意味着它将运行一次事件循环已启动(如果已启动则返回)。您可以在该页面的以下评论中看到对事件循环的依赖(作者:Jacob Levy):
我的猜测是,您正在运行普通的 Tclsh,这意味着您永远不会进入事件循环(Wish shell 在脚本末尾进入事件循环,而 Tcl shell 不会)。进入事件循环的标准方法是在到达 Tcl 代码末尾时运行以下命令:
也就是说,vwait 之后的任何内容都不会运行,直到退出事件循环之后。如果您希望 httpd 与您的代码并行运行,您需要:
希望有帮助。
Completely edited based on the OP's comments...
The after 0 trick is the following line:
What this does is tell the interp to add the command in question ($http eval $cmd) to the event queue, which means it will run once the event loop is started (or returned to if it's already started). You can see the reliance on the event loop in the following comment from that page (by Jacob Levy):
My guess is that you're running a plain Tclsh, which means you never enter the event loop (the Wish shell enters the event loop at the end of the script, the Tcl shell does not). The standard way to enter the event loop is to run the following command once you get to the end of your Tcl code:
That being said, anything you have after the vwait will not run until after the event loop is exited. If you want the httpd to run in parallel to your code, you need to either:
Hope that helps.
如果我正确理解了你想要做什么,你的代码应该类似于:
这样你就可以让 TclHttpd 在线程中运行,而不用担心 vwait 问题
如果你还想在执行过程中收到有关任何错误的通知httpd 执行时,TclHttp 将所有错误发送到日志文件。您可以配置日志的路径:
您需要有 httpd::log 包。
我希望这有帮助。
If I've understood correctly what you want to do, your code should look similar to that:
In this way you'll have TclHttpd running in a thread, without worrying for the vwait problem
If you also want to be informed about any error during the httpd execution, TclHttp sends all the errors to a log file. You can configure the path of the Log doing:
You need to have the httpd::log package.
I hope this helps.