Получить трассировку стека по ошибке 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
? Какой лучший способ?
Ответы
Ответ 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")
Ответ 4
Я настоятельно рекомендую Джо Ченга https://github.com/rstudio/shiny/wiki/Stack-traces-in-R. Это было действительно полезно для меня в этом вопросе.