Подтвердить что ты не робот

Получить трассировку стека по ошибке tryCatch' в R

Это связано с некоторыми другими вопросами, но я не могу понять, как применить ответ, поэтому я задаю новый вопрос.

Я пытаюсь выяснить неинформативную ошибку из фрагмента кода, который выглядит так:

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? Какой лучший способ?

4b9b3361

Ответ 1

Для интерактивного использования вы можете 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 "обработал" ошибку.

Ответ 2

Да, это возможно. Это не слишком элегантно в кодировании, но очень полезно в работе! Любые комментарии приветствуются!

Я поместил его в свой пакет 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" ))

Это стек ошибок:

tryStack (верхний ( "4" ))

верхняя ( "4" )

ниже (b)

Ошибка в + 10: нечисловой аргумент для двоичного оператора

Ответ 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")