How to retry a statement on error?
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 <- NULLattempt <- 1while( is.null(r) && attempt <= 3 ) { attempt <- attempt + 1 try( r <- some_function_that_may_fail() )}
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.
A solution without pre-assigning values and using for
instead of while
:
some_function_that_may_fail <- function(i) { if( runif(1) < .5 ) stop() return(i)}for(i in 1:10){ try({ r <- some_function_that_may_fail(i) break #break/exit the for-loop }, silent = FALSE)}
r
will be equal to the number of tries that were needed. If you dont want the output of the errors set silent
to TRUE