NiceLeeのBlog 用爱发电 bilibili~

Python 关于装饰器(以异常重试为例)

2021-02-01
nIceLee

阅读:


以抛出异常重试为例。

前言

具体的理解可以参考https://www.runoob.com/w3cnote/python-func-decorators.html
讲得挺明白的。
装饰器的本质是一个函数或者类。
为了方便记忆与理解,我将它记为C/C++里面类似define的语法糖(但实质比这更复杂)。
举例如下:

@xxx
def func(*arg, **kwargs):
    pass
'''
以下两种运行方法等同
result = func("若干参数")
result = xxx(func)("若干参数")

上述xxx可以是函数实现dec_fun  
也可以是带参数的函数实现dec_fun(*arg, **kwargs)
还可以是类实现dec_class(*arg, **kwargs)
总之,xxx这一坨需要实现一个功能,即写法xxx(func)返回一个函数,该函数大体输入输出应该与func一致
'''

示例代码

# coding=utf-8
import requests
import time
from functools import wraps

def retry(func):
    retry = 3
    sleep = 1
    def checkRun(retry, *args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            if(retry == 0):
                raise e
            else:
                time.sleep(sleep)
                return checkRun(retry-1, *args, **kwargs)
                
    @wraps(func)      
    def run(*args, **kwargs):
        return checkRun(retry, *args, **kwargs)
    return run

def retryWithParam(retry = 3, sleep = 1):
    def decoratedRetry(func):
        def checkRun(retry, *args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                if(retry == 0):
                    raise e
                else:
                    time.sleep(sleep)
                    return checkRun(retry-1, *args, **kwargs)
                    
        @wraps(func)      
        def run(*args, **kwargs):
            return checkRun(retry, *args, **kwargs)
        return run
    return decoratedRetry
    
class retryWithClass(object):
    def __init__(self, retry = 3, sleep = 1):
        self.retry = retry
        self.sleep = sleep
 
    def __call__(self, func):
        def checkRun(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                if(self.retry == 0):
                    raise e
                else:
                    self.retry -= 1
                    time.sleep(self.sleep)
                    return checkRun(*args, **kwargs)
                    
        @wraps(func)
        def run(*args, **kwargs):
            return checkRun(*args, **kwargs)
            
        return run 

#@retry
#@retryWithParam(retry = 2)
#@retryWithClass(retry = 1)  
def do_something(param = 1):
    print("do_something")
    return param


@retry
#@retryWithParam(retry = 2)
#@retryWithClass(retry = 1)  
def do_error(param = 1):
    print("do_error")
    1/0
    return param
    
if __name__ == '__main__':
    result = do_error("decoratedRetry")
    print(result)
    
    #retry(do_something)(参数)
    func1 = retry(do_something)
    result = func1("retry")
    print(result)
    
    #retryWithParam(retry = 2)(do_something)(参数)
    func2 = retryWithParam(retry = 2)(do_something)
    result = func2("retryWithParam")
    print(result)
    
    #retryWithClass(retry = 1)(do_something)(参数)
    func3 = retryWithClass(retry = 1)(do_something)
    result = func3("retryWithClass")
    print(result)


内容
隐藏