Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retry a statement on error?

How can I simply tell R to retry a statement a few times if it errors? E.g. I was hoping to do something like:

tryCatch(dbGetQuery(...),           # Query database     error = function(e) {         if (is.locking.error(e))    # If database is momentarily locked             retry(times = 3)        # retry dbGetQuery(...) 3 more times         else {             # Handle other errors         }     } ) 
like image 259
mchen Avatar asked Dec 25 '13 08:12

mchen


People also ask

How do you handle errors in R?

In R Programming, there are basically two ways in which we can implement an error handling mechanism. Either we can directly call the functions like stop() or warning(), or we can use the error options such as “warn” or “warning. expression”.


2 Answers

I usually put the try block in a loop, and exit the loop when it no longer fails or the maximum number of attempts is reached.

some_function_that_may_fail <- function() {   if( runif(1) < .5 ) stop()   return(1) }  r <- NULL attempt <- 1 while( is.null(r) && attempt <= 3 ) {   attempt <- attempt + 1   try(     r <- some_function_that_may_fail()   ) }  
like image 187
Vincent Zoonekynd Avatar answered Sep 20 '22 12:09

Vincent Zoonekynd


I wrote a quick function that allows you to easily retry an operating a configurable number of times, with a configurable wait between attempts:

library(futile.logger) library(utils)  retry <- function(expr, isError=function(x) "try-error" %in% class(x), maxErrors=5, sleep=0) {   attempts = 0   retval = try(eval(expr))   while (isError(retval)) {     attempts = attempts + 1     if (attempts >= maxErrors) {       msg = sprintf("retry: too many retries [[%s]]", capture.output(str(retval)))       flog.fatal(msg)       stop(msg)     } else {       msg = sprintf("retry: error in attempt %i/%i [[%s]]", attempts, maxErrors,                      capture.output(str(retval)))       flog.error(msg)       warning(msg)     }     if (sleep > 0) Sys.sleep(sleep)     retval = try(eval(expr))   }   return(retval) } 

So you can just write val = retry(func_that_might_fail(param1, param2), maxErrors=10, sleep=2) to retry calling that function with those parameters, give up after 10 errors, and sleep 2 seconds between attempts.

Also, you can redefine the meaning of what an error looks like by passing a different function as parameter isError, which by default will catch an error signaled with stop. This is useful if the function being called does something else on error, such as returning FALSE or NULL.

This is the alternative I've found so far that results in clearer, more readable code.

Hope this helps.

like image 29
asieira Avatar answered Sep 17 '22 12:09

asieira