Capture stdout within a TCL catch command

杀马特。学长 韩版系。学妹 提交于 2021-02-16 14:44:28

问题


In my main tcl script, I am calling a tcl proc wrapped in a catch command. This proc in-turn calls 10 more procs.

When there is an error in execution in any of those 10 procs, TCL still continues execution of my main script as expected and I am just able to view the error message which I captured. This error message may/may-not be conclusive enough to determine which of the 10 procs errored out during execution.

Is there a way to still keep capturing all the stdout until the point of error? I know it can be done by writing all messages (puts statements) in those 10 procs to another log file. But I'm interested in knowing if there is any other way.


回答1:


The catch command doesn't intercept I/O at all. To intercept output, the simplest and most method is to put a channel transform on that channel with chan 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]
    }
}

How to use this 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"}]

Output (I assume you recognise ASCII codes; the 13 10 at the end is a carriage-return/new-line sequence):

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



回答2:


catch won't capture the stdout of a Tcl procedure, it will capture the return value.

A demo in an interactive tclsh:

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


来源:https://stackoverflow.com/questions/64547745/capture-stdout-within-a-tcl-catch-command

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!