20

这与其他一些问题有关,但我似乎无法弄清楚如何应用答案,所以我问了一个新问题。

我试图从一段看起来像这样的代码中找出一个无意义的错误:

tryCatch(MainLoop(), 
  error=function(e) { fatal(lgr, paste('caught fatal error:', as.character(e))); 
                      exit.status <<- 1 })

问题是该错误似乎与隐藏在库函数中的某些内容有关:

Error in nrow(x): (subscript) logical subscript too long

nrow不在我的代码中,因为上面的 C 级错误仅适用于我的任何nrow调用中都不会发生的索引类型。

所以我真的很想从里面得到一个堆栈跟踪tryCatch。这是一个类似的问题:

x <- function() { y(); }
y <- function() { z(); }
z <- function() { stop("asdf") }

> x()
Error in z() : asdf
> tryCatch(x(), error=function(e) { print(conditionCall(e)) } )
z()
> tryCatch(x(), error=function(e) { dump.frames() } )
> last.dump
$`tryCatch(x(), error = function(e) {
    dump.frames()
})`
<environment: 0x1038e43b8>

$`tryCatchList(expr, classes, parentenv, handlers)`
<environment: 0x1038e4c60>

$`tryCatchOne(expr, names, parentenv, handlers[[1]])`
<environment: 0x1038e4918>

$`value[[3]](cond)`
<environment: 0x1038ea578>

attr(,"error.message")
[1] "asdf"
attr(,"class")
[1] "dump.frames"

如何获取包含调用的堆栈跟踪y()?我必须停止使用tryCatch吗?有什么更好的方法?

4

4 回答 4

19

对于交互式使用,可以trace(stop, quote(print(sys.calls())))在调用时打印调用堆栈stop()

?tryCatch,

 The function 'tryCatch' evaluates its expression argument in a
 context where the handlers provided in the '...'  argument are
 available.

然而

 Calling handlers are established by 'withCallingHandlers'...
 the handler is called... in the context where the condition
 was signaled...

所以

>     withCallingHandlers(x(), error=function(e) print(sys.calls()))
[[1]]
withCallingHandlers(x(), error = function(e) print(sys.calls()))

[[2]]
x()

[[3]]
y()

[[4]]
z()

[[5]]
stop("asdf")

[[6]]
.handleSimpleError(function (e) 
print(sys.calls()), "asdf", quote(z()))

[[7]]
h(simpleError(msg, call))

Error in z() : asdf

如果有内部 tryCatch,这将被阻止

withCallingHandlers({
    tryCatch(x(), error=function(e) stop("oops"))
}, error=function(e) print(sys.calls()))

因为我们只能在 tryCatch '处理'错误之后访问调用堆栈。

于 2013-03-07T23:27:30.783 回答
3

是的,有可能。它在编码方面不太优雅,但对输出很有帮助!欢迎任何意见!

我把它放在我的 misc 包中,如果你想要文档,可以从那里使用它。 https://github.com/brry/berryFunctions/blob/master/R/tryStack.R 下一个CRAN版本计划很快发布,到那时:

devtools::install_github("brry/berryFunctions")
# or use:
source("http://raw.githubusercontent.com/brry/berryFunctions/master/R/instGit.R")
instGit("brry/berryFunctions")

library(berryFunctions)
?tryStack

这是为了快速参考:

tryStack <- function(
expr,
silent=FALSE
)
{
tryenv <- new.env()
out <- try(withCallingHandlers(expr, error=function(e)
  {
  stack <- sys.calls()
  stack <- stack[-(2:7)]
  stack <- head(stack, -2)
  stack <- sapply(stack, deparse)
  if(!silent && isTRUE(getOption("show.error.messages"))) 
    cat("This is the error stack: ", stack, sep="\n")
  assign("stackmsg", value=paste(stack,collapse="\n"), envir=tryenv)
  }), silent=silent)
if(inherits(out, "try-error")) out[2] <- tryenv$stackmsg
out
}

lower <- function(a) a+10
upper <- function(b) {plot(b, main=b) ; lower(b) }

d <- tryStack(upper(4))
d <- tryStack(upper("4"))
cat(d[2])

d <- tryStack(上(“4”))

这是错误堆栈:

尝试堆栈(上(“4”))

上(“4”)

较低(b)

+ 10 中的错误:二元运算符的非数字参数

于 2016-11-30T22:54:31.577 回答
3

我是evaluate::try_capture_stack().

x <- function() {
  y()
}
y <- function() {
  z()
}
z <- function() {
  stop("asdf")
}
env <- environment()
e <- evaluate::try_capture_stack(quote(x()), env)
names(e)
#> [1] "message" "call"    "calls"
e$calls
#> [[1]]
#> x()
#> 
#> [[2]]
#> y()
#> 
#> [[3]]
#> z()
#> 
#> [[4]]
#> stop("asdf")
于 2018-06-05T17:18:13.473 回答
0

我参加聚会有点晚了,但我发现最好的方法是在您尝试的函数中使用退出处理程序。

main <- function()
{
  on.exit({
    msg <- capture.output(traceback())
    if (msg != "No traceback available ")
    {
      print(msg)
    }
  }
  )
  # rest of code
}

withCallingHandlers(
  expr =
    {
      main()
    },
  error = function(e) 
  {
    print(e)
  }
)
于 2019-11-11T16:26:17.347 回答