TCL/TK - 如何捕获包中的 stderr 输出?

TCL/TK - how does one capture stderr output from a package?

我有一个应用程序使用了一些包。查看他们的源代码,我发现他们正在做一个简单的 puts stderr ... 来转储调试信息。问题是如果你用 FreeWrap 或 TDK 之类的东西包装程序,你将无法访问控制台;所以我们想将该 stderr 输出转发到一个文件,以便我们可以看到正在打印的内容。

我在 Whosebug 的某个地方看到,您可以简单地关闭 stderr 频道,打开一个新频道,它应该会自动替换最近关闭的频道,如下所示:

close stderr
set out [open "outfile.txt" w]

puts stderr "hello world" # should output to the file 

不幸的是,这不起作用。当我尝试时,我收到错误消息:can not find channel named "stderr"

您可以重写 puts 以便可以截获到 stderr 的打印:

set error_file [open "outfile.txt" w]

rename puts __tcl__puts

proc puts {args} {
    if {[llength $args] == 2 && [lindex $args 0] eq "stderr"} {
        set args [list $::error_file [lindex $args end]]
    }
    __tcl__puts {*}$args
}

这个问题已经解决了很多次:使用通道拦截器(之前介绍过,):

通道拦截器实现为通道转换; here 之前已经介绍过。

第 1 步:定义通道拦截器

oo::class create ChannelSink {
    variable fileHandle
    method initialize {handle mode} {
        set fileHandle [open "outfile.txt" w]
        fconfigure $fileHandle -translation binary
        return {finalize initialize write}
    }
    method finalize {handle} {
        catch {close $fileHandle}
    }

    method write {handle bytes} {
        puts -nonewline $fileHandle $bytes 
        return
    }
}

以上代码段来自 Donal's

第 2 步:在您的打印代码

周围使用 stderr 注册拦截器
set cs [ChannelSink new]
chan push stderr $cs

puts stderr "hello world"

chan pop stderr