How to Check Whether a Function Call Results in a Warning

How can I check whether a function call results in a warning?

If you want to use the try constructs, you can set the options for warn. See also ?options. Better is to use tryCatch() :

x <- function(i){
if (i < 10) warning("A warning")
i
}

tt <- tryCatch(x(5),error=function(e) e, warning=function(w) w)

tt2 <- tryCatch(x(15),error=function(e) e, warning=function(w) w)

tt
## <simpleWarning in x(5): A warning>

tt2
## [1] 15

if(is(tt,"warning")) print("KOOKOO")
## [1] "KOOKOO"

if(is(tt2,"warning")) print("KOOKOO")

To get both the result and the warning :

tryCatch(x(5),warning=function(w) return(list(x(5),w)))

## [[1]]
## [1] 5
##
## [[2]]
## <simpleWarning in x(5): A warning>

Using try

op <- options(warn=2)

tt <- try(x())
ifelse(is(tt,"try-error"),"There was a warning or an error","OK")
options(op)

Catch warnings from functions in R and still get their return-value?

Borrowing some poorly documented R magic demonstrated in this post, I think the following revised laus() function will do the trick:

laus <- function(x) {
r <-
tryCatch(
withCallingHandlers(
{
error_text <- "No error."
list(value = hurz(x), error_text = error_text)
},
warning = function(e) {
error_text <<- trimws(paste0("WARNING: ", e))
invokeRestart("muffleWarning")
}
),
error = function(e) {
return(list(value = NA, error_text = trimws(paste0("ERROR: ", e))))
},
finally = {
}
)

return(r)
}

Now I can call laus(3) and get:

$value
[1] 12345

$error_text
[1] "No error."

or laus(NULL) and get:

$value
[1] 12345

$error_text
[1] "WARNING: simpleWarning in max(x): no non-missing arguments to max; returning -Inf"

or laus(foo) and get:

$value
[1] NA

$error_text
[1] "ERROR: Error in hurz(x): object 'foo' not found"

Note the use of <<- in the warning function. This searches the enclosing frames of the warning function and overwrites the error_text value in the environment of the anonymous function that calls hurz.

I had to use a debugger with a breakpoint in the warning function to figure out the enclosing frames. If you don't understand environments and frames in R, just trust that using <<- in this context will overwrite that error_text variable that is initialized to "No error."

To understand this code a bit better, realize that withCallingHandlers() is itself a stand-alone function. This is illustrated by the following variation of the function, which will trap and recover from warnings, but will NOT handle errors:

lausOnlyHandleWarnings <- function(x) {
r <-
withCallingHandlers(
{
error_text <- "No error."
list(value = hurz(x), error_text = error_text)
},
warning = function(e) {
error_text <<- trimws(paste0("WARNING: ", e))
invokeRestart("muffleWarning")
}
)

return(r)
}

The output from this function will be identical to the laus() function, unless there is an error. In the case of an error, it will simply fail and report the error, as would any other function that lacks a tryCatch. For instance, lausOnlyHandleWarnings(foo) yields:

Error in hurz(x) : object 'foo' not found

How to detect warnings in R and have a while loop run on a function as along as warnings are outputted?

You can use tryCatch() function to catch errors and warnings and adjust your workflow based on the result, i.e:

x = -3.5

repeat{

x <- x + 0.6
print( paste("Current value of x is", x) )

result <- tryCatch( log( x ),
error = function(e) e,
warning = function(w) w )

if (inherits(result,"warning")) next # For warnings - continue the next iteration
if (inherits(result,"error")) stop( result ) # For errors - stop


print( paste0(" log(",x,")=", result))
break
}

# [1] "Current value of x is -2.9"
# [1] "Current value of x is -2.3"
# [1] "Current value of x is -1.7"
# [1] "Current value of x is -1.1"
# [1] "Current value of x is -0.5"
# [1] "Current value of x is 0.1"
# [1] " log(0.1)=-2.30258509299404"

However, be very careful with repeat and while loops as you might end up creating an infinite loop. It might be a good idea to check how many iterations the loop has executed and abort it in case there have been too many iterations:

x = -3.5
iter <- 0

while (iter < 100) {

x <- x + 0.6
iter <- iter + 1

print( paste("Current value of x is", x) )

result <- tryCatch( log( x ),
error = function(e) e,
warning = function(w) w )

if (inherits(result,"warning")) next # For warnings - continue the next iteration
if (inherits(result,"error")) stop( result ) # For errors - stop


print( paste0(" log(",x,")=", result))
break
}

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)

Check whether certain function is used inside a nested function in R

You could use the all.names function. It pulls out the names of all the variables/function defined inside the function

all.names(body(foo))
# [1] "{" "select" "df" "!" "!" "sym"
# [7] "x"

Part of the problem with your specific example is that !!sym isn't really a simple variable. It's more like a call to !(!(sym)) to the parser. The !! stuff really isn't a special operator to the R parser, it's just two calls to the negation operator which rlang re-interprets via non-standard evaluation.

How to test whether a function called from within a tkinter GUI yields a RunTimeWarning?

If the warning extended Warning (which RuntimeWarning should), you should be able to catch it with the catch_warnings context manager, see here for an example.

But you should be able to do something like:

import warnings
with warnings.catch_warnings(record=True) as w:
outside_function(...)
# code to check if there was a warning
if len(w) > 0:
# do something, e.g. check to see the warning type/whatnot

R Error Handling - how to ask whether user wants to proceed when a Warning appears

You can use tryCatch.

Suppose I want to convert character strings to numbers. Ordinarily, if a character vector contains some strings that can't be coerced into numbers, then calling as.numeric on the vector will proceed without error, but will emit a warning saying that NA values have been introduced by coercion.

If I want more control over this process by being explicitly asked whether to go ahead with the conversion when NAs are going to be produced by coercion, then I could do:

convert_to_numeric <- function(x) {

tryCatch({
as.numeric(x)
},
warning = function(w) {
cat("Warning!", w$message, '\n')
cont <- readline('Do you wish to continue? [Y/N] ')
if(cont != 'Y') stop('Aborted by user')
return(suppressWarnings(as.numeric(x)))
}
)
}

Which results in the following behaviour:

convert_to_numeric(c('1', '2', '3'))
#> [1] 1 2 3

convert_to_numeric(c('1', '2', 'banana'))
#> Warning! NAs introduced by coercion
Do you wish to continue? [Y/N] Y
#> [1] 1 2 NA

convert_to_numeric(c('1', '2', 'banana'))
#> Warning! NAs introduced by coercion
Do you wish to continue? [Y/N] N
#> Error in value[[3L]](cond) : Aborted by user


Related Topics



Leave a reply



Submit