2012-10-29 144 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)}))