r - How do I save warnings and errors as output from a function? -
i'm using lapply
run complex function on large number of items, , i'd save output each item (if any) warnings/errors produced can tell item produced warning/error.
i found way catch warnings using withcallinghandlers
(described here: https://stackoverflow.com/questions/4947528). however, need catch errors well. can wrapping in trycatch
(as in code below), there better way it?
catchtolist <- function(expr) { val <- null mywarnings <- null whandler <- function(w) { mywarnings <<- c(mywarnings, w$message) invokerestart("mufflewarning") } myerror <- null ehandler <- function(e) { myerror <<- e$message null } val <- trycatch(withcallinghandlers(expr, warning = whandler), error = ehandler) list(value = val, warnings = mywarnings, error=myerror) }
sample output of function is:
> catchtolist({warning("warning 1");warning("warning 2");1}) $value [1] 1 $warnings [1] "warning 1" "warning 2" $error null > catchtolist({warning("my warning");stop("my error")}) $value null $warnings [1] "my warning" $error [1] "my error"
there several questions here on discuss trycatch
, error handling, none found address particular issue. see how can check whether function call results in warning?, warnings() not work within function? how can 1 work around this?, , how tell lapply ignore error , process next thing in list? relevant ones.
maybe same solution, wrote factory
convert plain old functions functions capture values, errors, , warnings, can
test <- function(i) switch(i, "1"=stop("oops"), "2"={ warning("hmm"); }, i) res <- lapply(1:3, factory(test))
with each element of result containing value, error, , / or warnings. work user functions, system functions, or anonymous functions (factory(function(i) ...)
). here's 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 helpers dealing 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)
Comments
Post a Comment