而循环装饰

时间:2016-09-27 19:48:31

标签: python

我正在使用ftp库,在下载一堆文件时非常挑剔。每20次尝试就会出现错误:

ftp.cwd(locale_dir)

所以,我所做的是修复它:

while True:
    try:
        ftp.cwd(locale_dir)
    except:
        continue
    break

我如何编写python装饰器来执行此操作,因为我必须在脚本中执行上述大约10 ftp命令。如果我有类似的东西会很好:

retry_on_failure(ftp.cwd(locale_dir))

2 个答案:

答案 0 :(得分:2)

您可以创建装饰器:

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

现在用这个装饰器创建你的文件下载功能:

@retry_on_failure(count=20)  # <- will make attempts upto 20 times if unable to downlaod 
def download_file(file_name):
    ftp.cwd(file_namee)

您可以将此装饰器与任何函数一起使用,在任何异常情况下您需要进行重试(不仅仅是文件下载功能)。这是decorators的美丽,这些是任何函数可以采用的通用;)

为了拨打download_file功能,请执行以下操作:

download_file(file_name)

答案 1 :(得分:1)

您无法使用所需的语法,因为代码ftp.cwd(locale_dir)retry_on_failure之前被调用,因此它引发的任何异常都会阻止retry函数运行。但是,您可以将函数及其参数分开,并调用类似retry_on_failure(ftp.cwd, (locale_dir,))的内容。

这是一个可以使用该语法的实现。 (注意,这不是装饰者,因为它通常用于Python。)

def retry_on_failure(func, args=(), kwargs={}):
    while True:
        try:
            return func(*args, **kwargs)
        except Exception:
            pass

如果函数始终引发异常,这当然会永远运行,因此请小心使用。您可以根据需要添加重复次数限制或添加日志记录。