使用 Python 装饰器重试请求

新手上路,请多包涵

我的脚本中有多个函数可以执行 REST API api 请求。因为我需要处理错误场景,所以我设置了如下重试机制。

 no_of_retries = 3
def check_status():
    for i in range(0,no_of_retries):
        url = "http://something/something"
        try:
            result = requests.get(url, auth=HTTPBasicAuth(COMMON_USERNAME, COMMON_PASSWORD)).json()
            if 'error' not in result:
                return result
            else:
                continue
        except Exception as e:
            continue
    return None

我有几种不同的方法可以执行类似的操作。我们怎样才能更好地避免重复可能是使用装饰器。

原文由 PGS 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 904
2 个回答

不使用装饰器,可能更好的解决方案是将请求移动到它自己的函数中,从而得到类似于以下的结构:

 no_of_retries = 3

def make_request(url):
    for i in range(0,no_of_retries):
        try:
            result = requests.get(url, auth=HTTPBasicAuth(COMMON_USERNAME, COMMON_PASSWORD)).json()
            if 'error' not in result:
                return result
            else:
                continue
        except Exception as e:
            continue
    return result

def check_status():
    result = make_request("http://something/status")

def load_file():
    result = make_request("http://something/file")

这样,您就可以在封装请求时避免重复代码。如果您要使用装饰器,则需要包装整个 load_file() 方法,这将阻止您在此函数中进一步处理请求的结果。

原文由 IonicSolutions 发布,翻译遵循 CC BY-SA 4.0 许可协议

您可以使用这样的装饰器并处理您自己的异常。

 def retry(times, exceptions):
    """
    Retry Decorator
    Retries the wrapped function/method `times` times if the exceptions listed
    in ``exceptions`` are thrown
    :param times: The number of times to repeat the wrapped function/method
    :type times: Int
    :param Exceptions: Lists of exceptions that trigger a retry attempt
    :type Exceptions: Tuple of Exceptions
    """
    def decorator(func):
        def newfn(*args, **kwargs):
            attempt = 0
            while attempt < times:
                try:
                    return func(*args, **kwargs)
                except exceptions:
                    print(
                        'Exception thrown when attempting to run %s, attempt '
                        '%d of %d' % (func, attempt, times)
                    )
                    attempt += 1
            return func(*args, **kwargs)
        return newfn
    return decorator

@retry(times=3, exceptions=(ValueError, TypeError))
def foo1():
    print('Some code here ....')
    print('Oh no, we have exception')
    raise ValueError('Some error')

foo1()

原文由 mrkiril 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题