How do I save warnings and errors as output from a function?
Maybe this is the same as your solution, but I wrote a factory
to convert plain old functions into functions that capture their values, errors, and warnings, so I can
test <- function(i) switch(i, "1"=stop("oops"), "2"={ warning("hmm"); i }, i)res <- lapply(1:3, factory(test))
with each element of the result containing the value, error, and / or warnings. This would work with user functions, system functions, or anonymous functions (factory(function(i) ...)
). Here's the factory
factory <- function(fun) function(...) { warn <- err <- NULL res <- withCallingHandlers( tryCatch(fun(...), error=function(e) { err <<- conditionMessage(e) NULL }), warning=function(w) { warn <<- append(warn, conditionMessage(w)) invokeRestart("muffleWarning") }) list(res, warn=warn, err=err) }
and some helpers for dealing with the result list
.has <- function(x, what) !sapply(lapply(x, "[[", what), is.null)hasWarning <- function(x) .has(x, "warn")hasError <- function(x) .has(x, "err")isClean <- function(x) !(hasError(x) | hasWarning(x))value <- function(x) sapply(x, "[[", 1)cleanv <- function(x) sapply(x[isClean(x)], "[[", 1)
Try the evaluate package.
library(evaluate)test <- function(i) switch(i, "1"=stop("oops"), "2"={ warning("hmm"); i }, i)t1 <- evaluate("test(1)")t2 <- evaluate("test(2)")t3 <- evaluate("test(3)")
It currently lacks a nice way of evaluating expression though - this is mainly because it's targetted towards reproducing exactly what R output's given text input at the console.
replay(t1)replay(t2)replay(t3)
It also captures messages, output to the console, and ensures that everything is correctly interleaved in the order in which it occurred.
I have merged Martins soulution (https://stackoverflow.com/a/4952908/2161065) and the one from the R-help mailing list you get with demo(error.catching)
.
The main idea is to keep both, the warning/error message as well as the command triggering this problem.
myTryCatch <- function(expr) { warn <- err <- NULL value <- withCallingHandlers( tryCatch(expr, error=function(e) { err <<- e NULL }), warning=function(w) { warn <<- w invokeRestart("muffleWarning") }) list(value=value, warning=warn, error=err)}
Examples:
myTryCatch(log(1))myTryCatch(log(-1))myTryCatch(log("a"))
Output:
> myTryCatch(log(1))
$value [1] 0 $warning NULL $error NULL
> myTryCatch(log(-1))
$value [1] NaN $warning $error NULL
> myTryCatch(log("a"))
$value NULL $warning NULL $error