Reputation: 110432
I am using the ftp
library which is incredibly finicky when downloading a bunch of files. This will error about once every 20 tries:
ftp.cwd(locale_dir)
So, what I do which fixes it is:
while True:
try:
ftp.cwd(locale_dir)
except:
continue
break
How would I write a python decorator to do this, as I have to do the above on about 10 ftp commands in a script. It would be nice if I could have something like:
retry_on_failure(ftp.cwd(locale_dir))
Upvotes: 4
Views: 5262
Reputation: 104792
You can't use the syntax you want, because in that code ftp.cwd(locale_dir)
gets called before retry_on_failure
, so any exception it raises will prevent the retry
function from running. You could separate the function and its arguments, however, and call something like retry_on_failure(ftp.cwd, (locale_dir,))
.
Here's an implementation that would work with that syntax. (Note, this isn't a decorator, as that's usually meant in Python.)
def retry_on_failure(func, args=(), kwargs={}):
while True:
try:
return func(*args, **kwargs)
except Exception:
pass
This will of course run forever if the function always raises an exception, so use with care. You could add a limit to the number of repetitions or add logging if you wanted to.
Upvotes: 1
Reputation: 48100
You may create decorator as:
def retry_on_failure(count=10): # <- default count as 10
def retry_function(function):
def wrapper(*args, **kwargs):
while count > 0:
try:
func_response = function(view, request, *args, **kwargs)
break # <- breaks the while loop if success
except:
count -= 1
func_response = None
return func_response
return wrapper
return retry_function
Now create your file download function with this decorator as:
@retry_on_failure(count=20) # <- will make attempts upto 20 times if unable to downlaod
def download_file(file_name):
ftp.cwd(file_namee)
You may use this decorator with any function, where you need to make a retry attempt in case of any exception (not just your file download function). This is the beauty of decorators
, these are generic adoptable by any function ;)
In order to make a call to download_file
fuction, just do:
download_file(file_name)
Upvotes: 4