在我的脚本中,我将引用其他所有者的 TCL 脚本。
我尝试检查所有变量是否在其 tcl 脚本文件中重新定义,这里我在我的脚本中尝试:
proc trace_var {args} {
set frame [info frame];
set frame_info [info frame [expr {$frame -2}]];
puts "$args set in $frame_info
}
trace add execution set leave trace_var
#source other owner script file
source #FILE_FROM_OTHERS
#file content:
set a 123
set b 123456 .....
#Just example, I don't know the all var name, in fact.
同时,tarce_var 中的设置也会被监听并打印消息。如何避免在trace_var中跟踪两个集合?
如果有更好的方法来进行此类追踪。
除了使用
set
命令之外,还有很多方法可以创建或更改变量,实在太多,无法尝试像这样进行监视。只是一些例子:
lassign $foo a b ;# variables a and b set / updated
dict set foo bar baz ;# variable foo set or updated
foreach element $list {} ;# variable element set
dict with foo {} ;# any keys in $foo become variables
这不限于 Tcl 内置命令,例如我的
json
命令与上述大多数示例具有等效项,因此除非您阻止您正在获取的脚本定义新命令,否则甚至无法跟踪通过跟踪所有可能影响变量的已知命令来实现它。
我不确定您的用例的详细信息,但如果它只是全局变量,我可能会尝试这样的事情:
proc var_changed {v n1 n2 op} {
puts "variable $v $op"
}
set start_vars [info vars]
foreach v $start_vars {
trace add variable $v {write unset} [list var_changed $v]
}
source $other_file
foreach v [info vars] {
if {$v ni $start_vars} {
puts "New var defined: $v"
}
}
在执行跟踪处理程序时,触发它的变量上的其他跟踪将被抑制。
此示例不处理数组变量或未设置然后又添加回来的变量可能发生的所有情况。可以将此技术扩展到名称空间中的变量,但它开始让人感觉脆弱且笨重。如果您的用例确实是关于包含内容未知的源脚本的副作用,那么我建议您在子解释器中获取脚本(如果您不信任脚本的来源,则为安全的子解释器),也许像这样:
set child [interp create -safe]
$child eval [list set foo $foo] ;# Copy the state of selected variables
$child eval [list set bar $bar] ;# to the child interp
$child eval [list source $other_file]
# Retrieve the state of vars in the child after sourcing $other_file if needed:
puts "foo in child: [$child eval [list set foo]]"
# Clean up
interp delete $child