在 TCL catch 命令中捕获标准输出

Capture stdout within a TCL catch command

在我的主 tcl 脚本中,我调用了一个包含在 catch 命令中的 tcl proc。 这个过程又调用了 10 个过程。

当这 10 个过程中的任何一个执行错误时,TCL 仍按预期继续执行我的主脚本,我只能查看我捕获的错误消息。此错误消息 may/may-not 足以确定 10 个过程中的哪一个在执行过程中出错。

有没有办法继续捕获所有标准输出直到出错? 我知道这可以通过将这 10 个过程中的所有消息(puts 语句)写入另一个日志文件来完成。但我很想知道是否还有其他方法。

catch 不会捕获 Tcl 过程的标准输出,它会捕获 return 值。

交互式 tclsh 中的演示:

% proc p {} {puts "some stdout"; return "return value"}
% catch p result
some stdout
0
% set result
return value

catch 命令根本不会拦截 I/O。要拦截输出,最简单和最简单的方法是在该通道上放置一个 channel transformchan push.

oo::class create Capture {
    variable contents encoding
    # Implement the channel interception protocol
    method initialize {handle mode} {
        set contents {}
        return {initialize finalize write}
    }   
    method finalize handle {
        # We do nothing here
    }
    method write {handle buffer} {
        append contents $buffer
        return $buffer
    }

    # Methods for ordinary people!
    method capture {channel body} {
        set encoding [chan configure $channel -encoding]
        chan push $channel [self]
        try {
            uplevel 1 $body
        } finally {
            chan pop $channel
        }
    }
    method contents {} {
        # Careful; need the encoding as channels work with binary data
        return [encoding convertfrom $encoding $contents]
    }
}

如何使用这个class:

set capt [Capture new]
$capt capture stdout {
    puts "Hello world!"
}
puts "Captured [string length [$capt contents]] characters"
puts [lmap c [split [$capt contents] ""] {scan $c "%c"}]

输出(我假设你认识ASCII码;最后的13 10是一个carriage-return/new-line序列):

Hello world!
Captured 14 characters
72 101 108 108 111 32 119 111 114 108 100 33 13 10