Search code examples
rtry-catchtry-catch-finally

How to tryCatch the same function call multiple times (N times) in R


We have a basic tryCatch that writes a dataframe to Google Sheets, and trys again if the first write fails for any reason:

result = tryCatch({
  print('TRYING')
  googlesheets4::sheet_write(data = our_df, ss = our_spreadsheet, sheet = 'our_sheetname')
}, error = function(e) {
  print('ERROR, TRYING AGAIN')
  googlesheets4::sheet_write(data = our_df, ss = our_spreadsheet, sheet = 'our_sheetname')
})

It is possible to generalize this code to retry the googlesheets4::sheet_write() function call for N number of tries? Is something built into base R for this or is there a good R library that handles unlimited retries of a function?


Solution

  • You can put it in a for loop like this.

    First, I am going to define a function that often fails (as I don't have access to your Google sheet).

    russian_roulette <- function(n = 6) {
        revolver <- sample(1:n, 1)
        if (revolver == 1) {
            return("You lived")
        } else {
            stop("Better luck next time...")
        }
    }
    

    Then you can try it as many times as you consider reasonable. You can replace my call to russian_roulette() with your call to googlesheets4::sheet_write().

    NUM_TRIES <- 10
    
    for (i in 1:NUM_TRIES) {
        message(i)
        result <- try({
            russian_roulette()
        })
        if (class(result) != "try-error") {
            print("Success!")
            break
        }
    }
    

    Output:

    1
    Error in russian_roulette() : Better luck next time...
    2
    Error in russian_roulette() : Better luck next time...
    3
    Error in russian_roulette() : Better luck next time...
    4
    Error in russian_roulette() : Better luck next time...
    5
    Error in russian_roulette() : Better luck next time...
    6
    [1] "Success!"
    
    result
    # [1] "You lived"
    

    I don't know why you expect writing to a file to fail - depending on the reason you may want to add a Sys.sleep() call in there for a certain number of seconds after every failure.