亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python重試模塊retrying

系統 1586 0

Python重試模塊retrying

工作中經常碰到的問題就是,某個方法出現了異常,重試幾次。循環重復一個方法是很常見的。比如爬蟲中的獲取代理,對獲取失敗的情況進行重試。
剛開始搜的幾個博客講的有點問題,建議看官方文檔,還有自己動手實驗。

參考:
https://segmentfault.com/a/1190000004085023
https://pypi.org/project/retrying/

最初的版本

          
            import requests

class ProxyUtil:

    def __init__(self):
        self._get_proxy_count = 0

    def get_proxies(self):
        try:
            r = requests.get('代理服務器地址')
            # print('正在獲取')
            # raise Exception("異常")
            # print('獲取到最新代理 = %s' % r.text)
            params = dict()
            if r and r.status_code == 200:
                proxy = str(r.content, encoding='utf-8')
                params['http'] = 'http://' + proxy
                params['https'] = 'https://' + proxy
            else:
                raise Exception("獲取代理失敗,狀態碼%s"%(r.status_code))
    
            return params
        except Exception:
            if self._get_proxy_count < 5:
                print('第%d次獲取代理失敗,準備重試' % self._get_proxy_count)
                self._get_proxy_count += 1
                self.get_proxies()
            else:
                print('第%d次獲取代理失敗,退出' % self._get_proxy_count)
                self._get_proxy_count = 0
                return dict()
if __name__ == '__main__':
    proxy = ProxyUtil()
    proxy.get_proxies()
          
        

以上代碼通過 try...except... 捕獲異常,并通過一個計數器判斷獲取代理的次數,獲取失敗遞歸調用自己,直到達到最大次數為止。
為了模擬失敗,可以解開拋出異常的注釋

下面來試試retrying模塊
安裝
pip install retrying

retrying提供一個裝飾器函數retry,被裝飾的函數會在運行失敗的情況下重新執行,默認一直報錯就一直重試。

          
            import requests
from retrying import retry

class ProxyUtil:

    def __init__(self):
        self._get_proxy_count = 0

    @retry
    def get_proxies(self):

        r = requests.get('代理地址')
        print('正在獲取')
        raise Exception("異常")
        print('獲取到最新代理 = %s' % r.text)
        params = dict()
        if r and r.status_code == 200:
            proxy = str(r.content, encoding='utf-8')
            params['http'] = 'http://' + proxy
            params['https'] = 'https://' + proxy

if __name__ == '__main__':
    proxy = ProxyUtil()
    proxy.get_proxies()
          
        

結果:

正在獲取
正在獲取
正在獲取
...
正在獲取(一直重復下去)
沒有添加任何參數,默認情況下會一直重試,沒有等待時間

          
            # 設置最大重試次數
@retry(stop_max_attempt_number=5)
def get_proxies(self):
    r = requests.get('代理地址')
    print('正在獲取')
    raise Exception("異常")
    print('獲取到最新代理 = %s' % r.text)
    params = dict()
    if r and r.status_code == 200:
        proxy = str(r.content, encoding='utf-8')
        params['http'] = 'http://' + proxy
        params['https'] = 'https://' + proxy
          
        
          
            # 設置方法的最大延遲時間,默認為100毫秒(是執行這個方法重試的總時間)
@retry(stop_max_attempt_number=5,stop_max_delay=50)
# 通過設置為50,我們會發現,任務并沒有執行5次才結束!
          
        
          
            # 添加每次方法執行之間的等待時間
@retry(stop_max_attempt_number=5,wait_fixed=2000)
# 隨機的等待時間
@retry(stop_max_attempt_number=5,wait_random_min=100,wait_random_max=2000)
# 每調用一次增加固定時長
@retry(stop_max_attempt_number=5,wait_incrementing_increment=1000)
          
        
          
            # 根據異常重試,先看個簡單的例子
def retry_if_io_error(exception):
    return isinstance(exception, IOError)

@retry(retry_on_exception=retry_if_io_error)
def read_a_file():
    with open("file", "r") as f:
        return f.read()
          
        

read_a_file 函數如果拋出了異常,會去 retry_on_exception 指向的函數去判斷返回的是 True 還是 False ,如果是 True 則運行指定的重試次數后,拋出異常, False 的話直接拋出異常。
當時自己測試的時候網上一大堆抄來抄去的,意思是 retry_on_exception 指定一個函數,函數返回指定異常,會重試,不是異常會退出。真坑人啊!
來看看獲取代理的應用(僅僅是為了測試retrying模塊)

          
            # 定義一個函數用于判斷返回的是否是IOError
def wraper(args):
    return isinstance(args,IOError)

class ProxyUtil:
    def get_proxies(self):
        r = requests.get('http://47.98.163.40:17000/get?country=local')
        print('正在獲取')
        raise IOError
        # raise IndexError
        print('獲取到最新代理 = %s' % r.text)
        params = dict()
        if r and r.status_code == 200:
            proxy = str(r.content, encoding='utf-8')
            params['http'] = 'http://' + proxy
            params['https'] = 'https://' + proxy

    # @retry_handler(retry_time=2, retry_interval=5, retry_on_exception=[IOError,IndexError])
    @retry(stop_max_attempt_number=5,retry_on_exception=wraper)
    def retry_test(self):
        self.get_proxies()
        print('io')
          
        

這種方法只能判斷單一的異常,而且擴展性不夠高

          
            # 通過返回值判斷是否重試
    def retry_if_result_none(result):
        """Return True if we should retry (in this case when result is None), False otherwise"""
        # return result is None
        if result =="111":
            return True


    @retry(stop_max_attempt_number=5,retry_on_result=retry_if_result_none)
    def might_return_none():
        print("Retry forever ignoring Exceptions with no wait if return value is None")
        return "111"

    might_return_none()
          
        

might_return_none 函數的返回值傳遞給 retry_if_result_none result ,通過判斷result,返回 Treu 或者 None 表示需要重試,重試結束后拋出 RetryError ,返回 False 表示不重試。
擴展默認的retry裝飾器:

          
            def retry_handler(retry_time: int, retry_interval: float, retry_on_exception: [BaseException], *args, **kwargs):

    def is_exception(exception: [BaseException]):
        for exp in retry_on_exception:
            if isinstance(exception,exp):
                return True
        return False
        # return isinstance(exception, retry_on_exception)

    def _retry(*args, **kwargs):
        return Retrying(wait_fixed=retry_interval * 1000).fixed_sleep(*args, **kwargs)

    return retry(
        wait_func=_retry,
        stop_max_attempt_number=retry_time,
        retry_on_exception=is_exception
    )

class ProxyUtil:
    def get_proxies(self):
        r = requests.get('代理地址')
        print('正在獲取')
        raise IOError
        # raise IndexError
        print('獲取到最新代理 = %s' % r.text)
        params = dict()
        if r and r.status_code == 200:
            proxy = str(r.content, encoding='utf-8')
            params['http'] = 'http://' + proxy
            params['https'] = 'https://' + proxy

    @retry_handler(retry_time=2, retry_interval=5, retry_on_exception=[IOError,IndexError])
    # @retry(stop_max_attempt_number=5,retry_on_exception=wraper)
    def retry_test(self):
        self.get_proxies()
        print('io')

if __name__ == '__main__':
    proxy = ProxyUtil()
    proxy.retry_test()
          
        

更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。?!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 亚洲精品一区二区三区www | 波多野结衣一区二区三区 | 伊人网站视频 | 波多野结衣av1区2区3区 | 国产精品亚洲专区在线播放 | 久久精品观看 | 日韩黄a级成人毛片 | 日本一区二区免费视频 | 日本久久一区二区 | 国产99在线 | 亚洲 | 4399一级成人毛片 | 92国产福利久久青青草原 | 欧美亚洲动漫 | 99久在线| 久久思 | 国产美女亚洲精品久久久久久 | 欧美www视频| 亚洲天堂一区二区三区四区 | 日本三级日本三级人妇三级四 | 日本不卡在线一区二区三区视频 | 中文字幕一区二区三区精品 | 久久99久久99精品免费看动漫 | 天天插天天射 | 欧美日韩不卡在线 | 交专区videossex另类 | 中文字幕三级久久久久久 | 亚洲精品中文字幕久久久久久 | 99久久99这里只有免费的精品 | 野花成人 | 欧美日韩乱码毛片免费观看 | 久久精品国产精品亚洲艾 | 久久免费视频在线 | 久久精品99视频 | 欧美大香a蕉免费 | 2022色婷婷综合久久久 | 国产成人a视频在线观看 | 日日摸夜夜爽日日放碰 | 精品中文字幕久久久久久 | 国产精品一区伦免视频播放 | sss欧美华人整片在线观看 | 99久热成人精品视频 |