當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


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。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。