R:如何使dump.frames()包含所有变量,以便以后使用debugger()进行事后调试

时间:2016-11-04 11:30:12

标签: r debugging lazy-evaluation environments rdebug

我有以下代码引发错误,并使用dump.frames() proposed e. g. by Hadley Wickham写入所有框架的转储:

a <- -1
b <- "Hello world!"
bad.function <- function(value)
{
  log(value)                  # the log function may cause an error or warning depending on the value
}

tryCatch( {
             a.local.value <- 42
             bad.function(a)
             bad.function(b)
          },
          error = function(e)
          {
            dump.frames(to.file = TRUE)
          })

当我重新启动R会话并加载转储以通过

调试问题时
load(file = "last.dump.rda")
debugger(last.dump)

我找不到我的变量(a,b,a.local.value)和我的函数&#34; bad.function&#34;框架中的任何地方。

这使得转储几乎对我毫无价值。

我需要做些什么来查看所有变量和函数以进行体面的事后分析

debugger的输出是:

> load(file = "last.dump.rda")
> debugger(last.dump)
Message:  non-numeric argument to mathematical functionAvailable environments had calls:
1: tryCatch({
    a.local.value <- 42
    bad.function(a)
    bad.function(b)
2: tryCatchList(expr, classes, parentenv, handlers)
3: tryCatchOne(expr, names, parentenv, handlers[[1]])
4: value[[3]](cond)

Enter an environment number, or 0 to exit  
Selection: 

PS:我正在使用R3.3.2和RStudio进行调试。

2 个答案:

答案 0 :(得分:3)

2016年11月20日更新: 请注意,它是 R错误(请参阅Martin Maechler的回答)。我没有改变我的重复性答案。所描述的工作仍然适用。

摘要

如果您想在新的R会话中调试批处理作业的错误,我认为dump.frames(to.file = TRUE)目前在R中是反模式(或可能是错误)。

你最好用

替换它
  dump.frames()
  save.image(file = "last.dump.rda")

options(error = quote({dump.frames(); save.image(file = "last.dump.rda")}))

而不是

options(error = dump.frames)

因为当您通过.GlobalEnv直接保存转储时,全局环境(dump.frames(to.file = TRUE) =您通常创建对象的用户工作空间)会包含在转储中,而丢失则会丢失。

影响分析

如果没有.GlobalEnv,您会丢失重要的顶级对象(及其当前值;-),以了解导致错误的代码行为!

特别是在“非交互式”R批处理作业出现错误的情况下,您将在没有.GlobalEnv的情况下丢失,因为您只能在新启动的(空)交互式工作区中进行调试只能访问调用堆栈帧中的对象。

使用上面的代码片段,您可以像往常一样检查导致新R工作区中的错误的对象值:

load(file = "last.dump.rda")
debugger(last.dump)

背景

dump.frames的实现在工作空间中创建了一个变量last.dump,并用调用堆栈的环境填充它(sys.frames()。每个环境都包含被调用的“局部变量”功能)。然后使用save()将此变量保存到文件中。

每次调用函数时,帧堆栈(调用堆栈)都会增长,请参阅?sys.frames

  

.GlobalEnv在帧列表中给出数字0。随后每一次   函数评估将帧堆栈增加1,用于评估该函数的环境由[...] sys.frame以适当的索引返回。

注意.GlobalEnv的索引编号为0。

如果我现在开始调试问题中代码生成的转储并选择第1帧(不是0!),我可以看到一个变量parentenv,它指向(引用).GlobalEnv:< / p>

Browse[1]> environmentName(parentenv)
[1] "R_GlobalEnv"

因此,我认为sys.frames不包含.GlobalEnv因此dump.frames(to.file = TRUE),因为它只存储sys.frames而没有.GlobalEnv的所有其他对象

也许我错了,但这看起来像一个不受欢迎的效果甚至是一个bug。 讨论欢迎!

参考

https://cran.r-project.org/doc/manuals/R-exts.pdf

摘自 4.2调试R代码(第96页)

部分
  

因为last.dump可以在以后甚至在另一个R会话中查看,   即使批量使用R,也可以进行验尸调试。我们这样做   需要安排转储保存:这可以做到   使用命令行标志    - 保存在运行结束时保存工作区,或通过

等设置保存      
    

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

  

答案 1 :(得分:2)

请注意,使用 R Core团队工作通常会更高效,而不仅仅是告诉R有错误。它显然没有错误,因为它的行为完全符合记录。

如果您以交互方式工作也没有问题,因为您可以完全访问工作区(可能是 LARGE ),因此问题仅适用于批处理作业(如您所述) )。

我们宁愿拥有的是缺少功能,功能请求(以及错误报告!)应该发生在R bug网站(又名_'R bugzilla'),https://bugs.r-project.org/上。 ..但通常在阅读R网站上的相应页面后https://www.r-project.org/bugs.html

请注意,R bugzilla是可搜索的,在目前的情况下,你很快就会发现Andreas Kersting提出了一个很好的建议(即作为一个愿望,而不是声称一个bug),     https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17116 因此我已经在8月16日向R添加了缺失的功能。 是的,当然是R的开发版,又名 R-devel 。 另见R-devel邮件列表中的今天帖子, https://stat.ethz.ch/pipermail/r-devel/2016-November/073378.html