python重試裝飾器的簡單實現

簡單實現了一個在函數執行出現異常時自動重試的裝飾器,支持控制最多重試次數,每次重試間隔,每次重試間隔時間遞增。python

最新的代碼能夠訪問從github上獲取git

https://github.com/blackmatrix7/matrix-toolkit/blob/master/toolkit/retry.pygithub

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2017/8/18 上午9:50
# @Author : Matrix
# @Github : https://github.com/blackmatrix7/
# @Blog : http://www.cnblogs.com/blackmatrix/
# @File : retry.py
# @Software: PyCharm
import time
from functools import wraps

__author__ = 'blackmatrix'


"""
在函數執行出現異常時自動重試的簡單裝飾器
"""


class StopRetry(Exception):

    def __repr__(self):
        return 'retry stop'


def retry(max_retries: int =5, delay: (int, float) =0, step: (int, float) =0,
          exceptions: (BaseException, tuple, list) =BaseException,
          sleep=time.sleep, callback=None, validate=None):
    """
    函數執行出現異常時自動重試的簡單裝飾器。
    :param max_retries:  最多重試次數。
    :param delay:  每次重試的延遲,單位秒。
    :param step:  每次重試後延遲遞增,單位秒。
    :param exceptions:  觸發重試的異常類型,單個異常直接傳入異常類型,多個異常以tuple或list傳入。
    :param sleep:  實現延遲的方法,默認爲time.sleep。
    在一些異步框架,如tornado中,使用time.sleep會致使阻塞,能夠傳入自定義的方法來實現延遲。
    自定義方法函數簽名應與time.sleep相同,接收一個參數,爲延遲執行的時間。
    :param callback: 回調函數,函數簽名應接收一個參數,每次出現異常時,會將異常對象傳入。
    可用於記錄異常日誌,中斷重試等。
    如回調函數正常執行,並返回True,則表示告知重試裝飾器異常已經處理,重試裝飾器終止重試,而且不會拋出任何異常。
    如回調函數正常執行,沒有返回值或返回除True之外的結果,則繼續重試。
    如回調函數拋出異常,則終止重試,並將回調函數的異常拋出。
    :param validate: 驗證函數,用於驗證執行結果,並確認是否繼續重試。
    函數簽名應接收一個參數,每次被裝飾的函數完成且未拋出任何異常時,調用驗證函數,將執行的結果傳入。
    如驗證函數正常執行,且返回False,則繼續重試,即便被裝飾的函數完成且未拋出任何異常。
    如回調函數正常執行,沒有返回值或返回除False之外的結果,則終止重試,並將函數執行結果返回。
    如驗證函數拋出異常,且異常屬於被重試裝飾器捕獲的類型,則繼續重試。
    如驗證函數拋出異常,且異常不屬於被重試裝飾器捕獲的類型,則將驗證函數的異常拋出。
    :return: 被裝飾函數的執行結果。
    """
    def wrapper(func):
        @wraps(func)
        def _wrapper(*args, **kwargs):
            nonlocal delay, step, max_retries
            func_ex = StopRetry
            while max_retries > 0:
                try:
                    result = func(*args, **kwargs)
                    # 驗證函數返回False時,表示告知裝飾器驗證不經過,繼續重試
                    if callable(validate) and validate(result) is False:
                        continue
                    else:
                        return result
                except exceptions as ex:
                    # 回調函數返回True時,表示告知裝飾器異常已經處理,終止重試
                    if callable(callback) and callback(ex) is True:
                        return
                    func_ex = ex
                finally:
                    max_retries -= 1
                    if delay > 0 or step > 0:
                        sleep(delay)
                        delay += step
            else:
                raise func_ex
        return _wrapper
    return wrapper


if __name__ == '__main__':
    pass
相關文章
相關標籤/搜索