python失败重试装饰器

使用场景:
比如在调用网络API时,提高成功率。
import requests
from datetime import datetime
import time
import random

retry_timeout = 10

def http_request(url, first_request_time=None, retry_counter=0):
    """
  first_request_time: The time of the first request (None if no retries have occurred).
  retry_counter: The number of this retry, or zero for first attempt.
  """
    if not first_request_time:
        first_request_time = datetime.now()

    try:
        elapsed = datetime.now() - first_request_time

        if elapsed.total_seconds() > retry_timeout:
            raise TimeoutError

        if retry_counter > 0:
            # 0.5 * (1.5 ^ i) is an increased sleep time of 1.5x per iteration,
            # starting at 0.5s when retry_counter=0. The first retry will occur
            # at 1, so subtract that first.
            delay_seconds = 0.5 * 1.5**(retry_counter - 1)
            print(f"Delay {delay_seconds}")
            # Jitter this value by 50% and pause.
            time.sleep(delay_seconds * (random.random() + 0.5))

        result = requests.get(url)
        return result.text

    except TimeoutError:
        print("Request Timed out")
        return None

    except requests.exceptions.ConnectionError:

        return http_request(url, first_request_time, retry_counter + 1)

if __name__ == "__main__":
    response_text = http_request("https://thissitedoesntexist.com")

# retries the request to an invalid url until the timeout of 10 second is reached
# A TimeoutError is raised after 10 seconds

  


这个实现一般就够用了,再复杂一点,有专门的
backoff退避算法。
 1 import time
 2 from functools import wraps
 3 
 4 
 5 def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None):
 6     """Retry calling the decorated function using an exponential backoff.
 7 
 8     http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/
 9     original from: http://wiki.python.org/moin/PythonDecoratorLibrary#Retry
10 
11     :param ExceptionToCheck: the exception to check. may be a tuple of
12         exceptions to check
13     :type ExceptionToCheck: Exception or tuple
14     :param tries: number of times to try (not retry) before giving up
15     :type tries: int
16     :param delay: initial delay between retries in seconds
17     :type delay: int
18     :param backoff: backoff multiplier e.g. value of 2 will double the delay
19         each retry
20     :type backoff: int
21     :param logger: logger to use. If None, print
22     :type logger: logging.Logger instance
23     """
24     def deco_retry(f):
25 
26         @wraps(f)
27         def f_retry(*args, **kwargs):
28             mtries, mdelay = tries, delay
29             while mtries > 1:
30                 try:
31                     return f(*args, **kwargs)
32                 except ExceptionToCheck, e:
33                     msg = "%s, Retrying in %d seconds..." % (str(e), mdelay)
34                     if logger:
35                         logger.warning(msg)
36                     else:
37                         print msg
38                     time.sleep(mdelay)
39                     mtries -= 1
40                     mdelay *= backoff
41             return f(*args, **kwargs)
42 
43         return f_retry  # true decorator
44 
45     return deco_retry

 



来源:https://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/
 
posted @ 2015-12-06 16:33  Jeff_blog  阅读(240)  评论(0编辑  收藏  举报