2012-10-29 194 views
22

我觀察到一個關於traceback()的交互式和非交互式R會話之間的不同,我不明白。對於下面的代碼,它會產生一個錯誤,但是在交互式R會話中,我可以看到回溯信息,而如果我將代碼保存到test.R並通過Rscript test.RR -f test.R調用它,我不會再看到回溯:traceback()用於交互式和非交互式R會話

f = function() { 
    on.exit(traceback()) 
    1 + 'a' 
} 
f() 

在交互式R對話:

> f = function() { 
+ on.exit(traceback()) 
+ 1 + 'a' 
+ } 
> f() 
Error in 1 + "a" : non-numeric argument to binary operator 
1: f() 

非交互式執行:

$ Rscript test.R 
Error in 1 + "a" : non-numeric argument to binary operator 
Calls: f 
No traceback available 
Execution halted 

我在?traceback沒有看到解釋,我想知道是否有辦法爲非交互式R會話啓用回溯。謝謝!

+0

'traceback'查找對象在'baseenv()'中調用'.Traceback'。它看起來像(從'src/main/errors.c'),只有在除其他條件之外'R_Interactive || haveHandler'。如果沒有'.Traceback',你將會得到「沒有回溯可用」的消息。 'traceback'還有一個警告提到'.Traceback'。 – BenBarnes

+0

如果您只是在腳本中設置選項(error = traceback),並刪除on.exit調用,您將獲得所需的效果。儘管由於錯誤的「步驟」它確實會造成重複。 –

+0

@BrandonBertelsen,據我所知,仍然不會允許您訪問追溯信息,儘管在非交互式會話中發生錯誤時無論如何都會返回調用堆棧。 – BenBarnes

回答

20

使用其參數的默認值,traceback()將在baseenv()中查找名爲.Traceback的對象以獲取有關調用堆棧的信息。它看起來像(從src/main/errors.c)像.Traceback只有在除其他條件,R_Interactive || haveHandler,建議此對象不在非交互式會話期間創建時纔會創建。如果沒有名爲.Traceback的對象,您將收到消息「無回溯可用」。

但是,通過將非NULL值傳遞給參數爲traceback()x,可以從非交互式會話中獲取有關調用堆棧的信息。使用非零整數值(表示在堆棧中跳過調用的次數),會調用c級函數(R_GetTraceback)調查調用堆棧,而不是查找.Traceback

因此,有幾種方法可以得到一個非交互式會話的跟蹤信息:

f = function() { 
    on.exit(traceback(1)) 
    1 + 'a' 
} 
f() 

或者設置options作爲布蘭登貝特爾森提示

options(error=function()traceback(2)) 

傳遞給x不同的值這兩個示例說明了要跳過的功能的不同數量

  1. on.exit示例中,traceback(1)跳過呼叫traceback()

  2. 在示例設置options中,有一個額外的匿名函數調用traceback(),它應該/也可以跳過。

在OP的例子中,有不使用traceback()相比在非交互式會話在發生錯誤的情況下,提供的自動追蹤獲得更多的信息。但是,對於採用(並通過)參數的函數,使用traceback()將比非交互式會話中的調用堆棧的標準表示更具信息性。

+0

非常感謝!我沒有意識到將'x'設置爲數字也適用於非交互式R會話。 –

+4

注意,即使發生錯誤,使用'options(error = function()traceback(2))'也會導致腳本成功退出!一個解決方案是使用'error = function(){traceback(2); if(!interactive())quit(「no」,status = 1,runLast = FALSE)}'instead(此處使用的停止參數來自[默認錯誤行爲](https://stat.ethz.ch/R -manual/R-devel的/庫/鹼/ HTML/stop.html))。 – dshepherd

2

還可以轉儲調試信息並稍後加載它們。(參見話題好?debugger幫助頁面和評論)

通過例如:

options(error = quote(dump.frames("testdump", TRUE))) 

...

load("testdump.rda") 
debugger(testdump) 

options(error = quote({dump.frames(to.file = TRUE); q(status = 1)}))