Retry function in Python

François M. picture François M. · Mar 1, 2017 · Viewed 22k times · Source

Some time ago, I was in need of a retry function in R to handle slow servers response. The function would have the following behavior : (try an action (function or method), and if it fails, wait a bit and then retry)x10

I came up with the following :

retry <- function(fun, max_trys = 10, init = 0){
  suppressWarnings(tryCatch({
    Sys.sleep(0.3);
    if(init<max_trys) {fun}
}, error=function(e){retry(fun, max_trys, init = init+1)}))}

It worked well. Now I need the same in Python3, so I tried to make the same code :

import time
def retry_fun(fun, max_trys = 10, init=0):
    try:
        time.sleep(0.3)
        if(init<max_trys):
            fun
    except:
        retry_fun(fun, max_trys, init = init+1)

But when I run it, it's crashing my kernel. As I'm a bit of a beginner in Python, I'm not sure what's causing the crash, and if/how a function can be passed as an argument into another function.

Could you help me out ?

Answer

Apart from being able to pass functions and use them by adding () after the name (Python's syntax for invoking calls), you don't need to use recursion; just put it in a loop:

import time
def retry(fun, max_tries=10):
    for i in range(max_tries):
        try:
           time.sleep(0.3) 
           fun()
           break
        except Exception:
            continue

except Exception should be changed to catch a meaningfull exception that the function might raise. Using Exception (as I did in the example) is generally bad practice since it catches a large class of exceptions that you might not of wanted caught.

Apart from that, using a for-loop instead of an explicit third counter and recursion (which leads to a long call-stack for large values) is better.