当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


R trace 函数或方法调用的交互式跟踪和调试


R语言 trace 位于 base 包(package)。

说明

调用trace允许您插入调试代码(例如,调用browser或者recover)在任何函数中的选定位置。调用untrace取消追踪。可以以相同的方式跟踪指定的方法,而无需跟踪对通用函数的所有调用。跟踪代码(tracer) 可以是任何R表达。可以通过调用全局暂时打开或关闭跟踪tracingState.

用法

trace(what, tracer, exit, at, print, signature,
      where = topenv(parent.frame()), edit = FALSE)
untrace(what, signature = NULL, where = topenv(parent.frame()))

tracingState(on = NULL)
.doTrace(expr, msg)
returnValue(default = NULL)

参数

what

要跟踪或不跟踪的函数的名称,可能是 quote() d。对于具有多个参数的untracetrace,可以在引号中给出多个名称,并且对每个名称应用相同的操作。对于命名空间中的 “hidden” 函数(例如 S3 方法),通常还需要指定 where = *

tracer

function 或未计算的表达式。将在调用开始时或在参数 at 指定的调用中的那些步骤之前调用函数或计算表达式。请参阅详细信息部分。

exit

function 或未计算的表达式。退出函数时将调用该函数或计算表达式。请参阅详细信息部分。

at

可选的数字向量或列表。如果提供,tracer 将在函数体中的相应步骤之前调用。请参阅详细信息部分。

print

如果TRUE(默认),则在计算任何跟踪表达式之前打印说明性行。

signature

如果提供此参数,它应该是函数 what 的方法的签名。在这种情况下,将跟踪方法而不是函数本身。

edit

对于复杂的跟踪,例如在函数内的循环内进行跟踪,您将需要通过编辑函数体来插入所需的调用。如果是这样,请将 edit 参数提供为 TRUE 或您要使用的编辑器的名称。然后trace()将调用edit并使用您编辑后的函数版本。有关更多信息,请参阅详细信息部分。

where

在哪里寻找要跟踪的函数;默认情况下,调用 trace 的顶级环境。

此参数的一个重要用途是跟踪 “hidden” 包中的函数或从另一个包调用的函数。命名空间机制导入要调用的函数(基础包中的函数除外)。被调用的函数是不是从顶层看到的相同对象(通常,导入的包甚至可能不附加)。因此,您必须确保跟踪正确的版本。做到这一点的方法是设置参数where到命名空间(或该命名空间)中的函数。然后,跟踪计算将开始在该函数的环境中查找(这将是相应包的命名空间)。 (是的,这很微妙,但是这里的语义对于命名空间如何工作至关重要R.)

on

逻辑性;如果全局打开跟踪,则对支持函数 tracingState 的调用将返回 TRUE,否则返回 FALSE。这些值中的一个或另一个的参数设置状态。如果跟踪状态为 FALSE ,则实际上不会发生任何跟踪操作(例如,通过调试函数在调试期间关闭跟踪)。

expr, msg

支持函数 .doTrace 的参数,对其的调用将插入到修改后的函数或方法中: expr 是跟踪操作(例如对 browser() 的调用),而 msg 是标识其中位置的字符串跟踪动作发生。

default

如果 returnValue 找不到返回值(例如,函数由于错误、重新启动或由于评估调用函数的返回值而退出),它将返回 default

细节

trace 函数通过构造函数(或方法,如果提供了 signature)的修订版本来运行,并将新对象分配回原始对象所在的位置。如果仅给出 what 参数,则每次调用该函数都会生成一行跟踪打印(向后兼容 trace 的早期版本)。

trace 构造的对象来自扩展"function" 的类,其中包含原始的、未跟踪的版本。调用 untrace 会重新分配此版本。

如果参数 tracerexit 是函数名称,则跟踪表达式将是对该函数的调用,不带参数。这是最简单和最常见的情况,函数 browserrecover 是最有可能的候选者;前者在被跟踪的函数框架中浏览,后者允许在任何当前活动的调用中浏览。对参数 tracerexit 进行评估以查看它们是否是函数,但在跟踪表达式中仅使用它们的名称。当跟踪函数执行时会再次进行查找,因此跟踪时可能不会调用tracerexit

tracerexit 参数也可以是未计算的表达式(例如通过调用 quotesubstitute 返回)。该表达式本身插入到跟踪函数中,因此它通常会涉及跟踪函数中的参数或本地对象。如果您只想在某些条件适用时进行交互,则这种形式的表达式非常有用(在这种情况下,您可能还想在对 trace 的调用中提供 print = FALSE)。

当提供 at 参数时,它可以是引用函数体子步骤的整数向量(仅当函数体包含在 { ...} 中时才有效)。在这种情况下,tracer 不会在进入时调用,而是在评估 at 中列出的每个步骤之前调用。 (提示:您不想尝试计算函数打印版本中的步骤;相反,请查看 as.list(body(f)) 以获取与函数 f 中的步骤关联的数字。)

at 参数也可以是整数向量列表。在这种情况下,每个向量引用函数的另一个步骤中嵌套的一个步骤。例如,at = list(c(3,4)) 将在函数第三步的第四步之前调用跟踪器。请参阅下面的示例。

使用 setBreakpoint (来自包 utils )可能是一种替代方法,调用 trace(...., at, ...)

exit 参数在 on.exit 处理期间调用。在on.exit表达式中,可以调用实验returnValue()函数来获取该函数将要返回的值。在其他情况下调用此函数将给出未定义的结果。

exit 参数的一个内在限制是,如果函数本身使用 on.exitadd= FALSE (默认),它将不起作用,因为现有调用将覆盖 trace 提供的调用。

跟踪不嵌套。对 trace 的任何调用都会替换该函数或方法之前跟踪的版本(除了下面讨论的编辑版本),并且 untrace 始终恢复未跟踪的版本。 (允许嵌套跟踪很可能会造成混乱,并且可能会意外留下跟踪版本。)

当重复使用 edit 参数且中间没有在同一函数或方法上调用 untrace 时,将保留先前编辑的版本。如果您想丢弃所有先前的跟踪然后进行编辑,请在下次调用 trace 之前调用 untrace 。编辑可与自动跟踪相结合;只需提供其他参数,例如 traceredit 参数。 edit = TRUE 参数使用默认编辑器(请参阅 edit )。

从基础包中跟踪原始函数(内置函数和特殊函数)是可行的,但只能通过特殊机制进行,并且信息量不大。跟踪原语会导致原语被带有参数的函数替换...(仅)。你可以得到一些信息,但不多。当在原语上使用 trace 时,会发出警告消息。

将函数的跟踪版本保存回函数来源的位置的做法意味着,如果跟踪函数保存在会话映像中,则跟踪会从一个会话转移到另一个会话。 (在下一个会话中,untrace 将删除跟踪。)另一方面,包中而不是全局环境中的函数不会保存在映像中,因此跟踪会随着此类函数的会话而过期。

跟踪 S4 方法本质上就像跟踪函数一样,不同之处在于跟踪版本是通过调用 setMethod 而不是直接赋值来存储的,调用 untrace 后的未跟踪版本也是如此。

的版本trace这里说明的在很大程度上与S-Plus中的版本兼容,尽管两者的工作机制完全不同。 S-Plustrace使用会话框架,其结果是跟踪永远不会从一个会话转移到另一个会话(R没有会话框架)。另一个相关的区别与以下内容没有直接关系trace:S-Plus中的浏览器允许对正在浏览的框架进行更改,并且退出浏览器后更改将保留。这R浏览器允许更改,但当浏览器退出时它们就会消失。这可能是相关的,因为 S-Plus 版本允许您交互地试验代码更改,但是R版本没有。 (未来的修订版可能包括 ‘destructive’ 浏览器R.)

在简单版本中(仅第一个参数), trace 返回不可见的 NULL 。否则,为跟踪的函数名称。相关的结果是发生的分配。

untrace 不可见地返回函数名称。

tracingState 返回当前全局跟踪状态,并可能更改它。

on.exit 处理期间调用时,returnValue 返回退出函数即将返回的值。其他情况下的行为未定义。

注意

使用 trace() 在概念上是 debug 的泛化,但实现方式不同。即通过tracerexit 参数调用browser

包含除函数名称之外的任何参数的函数跟踪版本需要 methods 包(因为它使用特殊的对象类来存储和恢复跟踪函数的版本)。

如果当前未启用方法调度,trace 将加载方法命名空间,但不会将方法包放在 search 列表中。

例子

require(stats)

##  Very simple use
trace(sum)
hist(rnorm(100)) # shows about 3-4 calls to sum()
untrace(sum)

## Show how pt() is called from inside power.t.test():
if(FALSE)
  trace(pt) ## would show ~20 calls, but we want to see more:
trace(pt, tracer = quote(cat(sprintf("tracing pt(*, ncp = %.15g)\n", ncp))),
      print = FALSE) # <- not showing typical extra
power.t.test(20, 1, power=0.8, sd=NULL)  ##--> showing the ncp root finding:
untrace(pt)



f <- function(x, y) {
    y <- pmax(y, 0.001)
    if (x > 0) x ^ y else stop("x must be positive")
}

## arrange to call the browser on entering and exiting
## function f
trace("f", quote(browser(skipCalls = 4)),
      exit = quote(browser(skipCalls = 4)))

## instead, conditionally assign some data, and then browse
## on exit, but only then.  Don't bother me otherwise

trace("f", quote(if(any(y < 0)) yOrig <- y),
      exit = quote(if(exists("yOrig")) browser(skipCalls = 4)),
      print = FALSE)

## Enter the browser just before stop() is called.  First, find
## the step numbers

untrace(f) # (as it has changed f's body !)
as.list(body(f))
as.list(body(f)[[3]]) # -> stop(..) is [[4]]

## Now call the browser there

trace("f", quote(browser(skipCalls = 4)), at = list(c(3,4)))
## Not run: 
f(-1,2) # --> enters browser just before stop(..)

## End(Not run)

## trace a utility function, with recover so we
## can browse in the calling functions as well.

trace("as.matrix", recover)

## turn off the tracing (that happened above)

untrace(c("f", "as.matrix"))

## Not run: 
## Useful to find how system2() is called in a higher-up function:
trace(base::system2, quote(print(ls.str())))

## End(Not run)

##-------- Tracing hidden functions : need 'where = *'
##
## 'where' can be a function whose environment is meant:
trace(quote(ar.yw.default), where = ar)
a <- ar(rnorm(100)) # "Tracing ..."
untrace(quote(ar.yw.default), where = ar)

## trace() more than one function simultaneously:
##         expression(E1, E2, ...)  here is equivalent to
##          c(quote(E1), quote(E2), quote(.*), ..)
trace(expression(ar.yw, ar.yw.default), where = ar)
a <- ar(rnorm(100)) # --> 2 x "Tracing ..."
# and turn it off:
untrace(expression(ar.yw, ar.yw.default), where = ar)


## Not run: 
## trace calls to the function lm() that come from
## the nlme package.
trace("lm", where = asNamespace("nlme"))
      lm    (len ~ log(dose) * supp, ToothGrowth) -> fit1  # NOT traced
nlme::lmList(len ~ log(dose) | supp, ToothGrowth) -> fit2  # traced
untrace("lm", where = asNamespace("nlme"))

## End(Not run)

参考

Becker, R. A., Chambers, J. M. and Wilks, A. R. (1988) The New S Language. Wadsworth & Brooks/Cole.

也可以看看

browserrecover ,最有可能的跟踪函数;另外,quotesubstitute 用于构造通用表达式。

相关用法


注:本文由纯净天空筛选整理自R-devel大神的英文原创作品 Interactive Tracing and Debugging of Calls to a Function or Method。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。