python之retry函數(爬蟲可用)


我們知道,在抓取數據時,多多少少會因為個別的原因(網絡不好等)出現請求的故障,這樣會影響我們抓取數據的效率,那遇到這樣的問題我們該怎么解決呢?直接用try模式?這樣會影響到抓取的數據量,這個時候retry函數就用到了。

首先安裝,很簡單pip install retry

然后就是講一下,retry函數的幾個參數的意義,當然如果英文夠好的可以直接看源代碼就可以官網。

各個參數的含義

def retry(exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1, jitter=0, logger=logging_logger):
    """Return a retry decorator.
    :param exceptions:捕獲異常或異常元組。 默認:Exception。
    :param tries:Exception最大嘗試次數。 默認值:-1(無限)。
    :param delay:嘗試之間的初始延遲。 默認值:0。
    :param max_delay:延遲的最大值。 默認值:無(無限制)。
    :param backoff:乘法器應用於嘗試之間的延遲。 默認值:1(無退避)。
    :param jitter:額外的秒數添加到嘗試之間的延遲。 默認值:0。
               如果數字固定,則隨機如果范圍元組(最小值,最大值)
    :param logger:logger.warning(fmt,error,delay)將在失敗嘗試中調用。
                    默認值:retry.logging_logger。 如果無,則記錄被禁用。
    """

①使用時,如果不帶參數會認為是默認的參數,那么遇到異常時會一直retry下去,直到成功

from retry import retry
 
@retry()
def make_trouble():
    '''Retry until succeed'''
    print ('retrying...')
    raise
 
if __name__ == '__main__':
    make_trouble()
 
# 輸出: 一直重試,直到運行成功
retrying...
retrying...
retrying...
retrying...
retrying...
retrying...

2.Exception參數, 默認 Exception, 只捕獲重試指定的異常,可以是元組

@retry(ZeroDivisionError, tries=3, delay=2)
def make_trouble():
    '''Retry on ZeroDivisionError, raise error after 3 attempts, sleep 2 seconds between attempts.'''
    print 'aaa'
    a = 1/0
 
if __name__ == '__main__':
    make_trouble()
 
輸出:
aaa
aaa
Traceback (most recent call last):
  File "E:/WORKSPACE/document/document/test/1.py", line 20, in <module>
    make_trouble()
  File "<decorator-gen-2>", line 2, in make_trouble
  File "D:\python27\WinPython-64bit-2.7.10.3\python-2.7.10.amd64\lib\site-packages\retry\api.py", line 74, in retry_decorator
    logger)
  File "D:\python27\WinPython-64bit-2.7.10.3\python-2.7.10.amd64\lib\site-packages\retry\api.py", line 33, in __retry_internal
    return f()
  File "E:/WORKSPACE/document/document/test/1.py", line 16, in make_trouble
    a = 1/0
ZeroDivisionError: integer division or modulo by zero
aaa

3.backoff參數,嘗試間隔時間,成倍數增加

import time
@retry((ValueError, TypeError), delay=1, backoff=2)
def make_trouble():
    '''Retry on ValueError or TypeError, sleep 1, 2, 4, 8, ... seconds between attempts.'''
    print (1,  int(time.time()))
 
    raise ValueError('a')
 
if __name__ == '__main__':
    make_trouble()
 
輸出:
(1, 1504107288)
(1, 1504107289)
(1, 1504107291)
(1, 1504107295)
(1, 1504107303)
(1, 1504107319)
(1, 1504107351)

4.max_delay 指定最大間隔時間,backoff參數觸發的休眠時間大於max_delay時,休眠時間以max_delay為准則

import time
 
@retry((ValueError, TypeError), delay=1, backoff=2, max_delay=8)
def make_trouble():
    '''Retry on ValueError or TypeError, sleep 1, 2, 4, 4, ... seconds between attempts.'''
 
    print (1, int(time.time()))
    raise ValueError('aa')
 
 
if __name__ == '__main__':
    make_trouble()
 
輸出:
(1, 1504107496)
(1, 1504107497)
(1, 1504107499)
(1, 1504107503)
(1, 1504107511)
(1, 1504107519)
(1, 1504107527)
(1, 1504107535)

5.jitter參數,累加,以及異常觸發的日志

import time
 
@retry(ValueError, delay=1, jitter=1)
def make_trouble():
    '''Retry on ValueError, sleep 1, 2, 3, 4, ... seconds between attempts.'''
    print (1, int(time.time()))
    raise ValueError('e')
 
if __name__ == '__main__':
    import logging
    logging.basicConfig()
    make_trouble()
 
輸出:
WARNING:retry.api:e, retrying in 1 seconds...
(1, 1504107644)
WARNING:retry.api:e, retrying in 2 seconds...
(1, 1504107645)
WARNING:retry.api:e, retrying in 3 seconds...
(1, 1504107647)
WARNING:retry.api:e, retrying in 4 seconds...
(1, 1504107650)
WARNING:retry.api:e, retrying in 5 seconds...
(1, 1504107654)
WARNING:retry.api:e, retrying in 6 seconds...
(1, 1504107659)
(1, 1504107665)
WARNING:retry.api:e, retrying in 7 seconds...
(1, 1504107672)
WARNING:retry.api:e, retrying in 8 seconds...

示例如下:

import requests
from retry.api import retry_call
 
def make_trouble(service, info=None):
    if not info:
        info = ''
    print ('retry..., service: {},  info: {}'.format(service, info))
    r = requests.get(service + info)
    print r.text
    raise Exception('info')
 
def what_is_my_ip(approach=None):
    if approach == "optimistic":
        tries = 1
    elif approach == "conservative":
        tries = 3
    else:
        # skeptical
        tries = -1
    result = retry_call(make_trouble, fargs=["http://ipinfo.io/"], fkwargs={"info": "ip"}, tries=tries)
    print(result)
 
if __name__ == '__main__':
    import logging
    logging.basicConfig()
    what_is_my_ip("conservative")
 
 
輸出:
retry..., service: http://ipinfo.io/,  info: ip
118.113.1.255
 
retry..., service: http://ipinfo.io/,  info: ip
WARNING:retry.api:info, retrying in 0 seconds...
WARNING:retry.api:info, retrying in 0 seconds...
118.113.1.255
 
retry..., service: http://ipinfo.io/,  info: ip
Traceback (most recent call last):
  File "E:/WORKSPACE/document/document/test/1.py", line 74, in <module>
    what_is_my_ip("conservative")
  File "E:/WORKSPACE/document/document/test/1.py", line 66, in what_is_my_ip
    result = retry_call(make_trouble, fargs=["http://ipinfo.io/"], fkwargs={"info": "ip"}, tries=tries)
  File "D:\python27\WinPython-64bit-2.7.10.3\python-2.7.10.amd64\lib\site-packages\retry\api.py", line 101, in retry_call
    return __retry_internal(partial(f, *args, **kwargs), exceptions, tries, delay, max_delay, backoff, jitter, logger)
  File "D:\python27\WinPython-64bit-2.7.10.3\python-2.7.10.amd64\lib\site-packages\retry\api.py", line 33, in __retry_internal
    return f()
  File "E:/WORKSPACE/document/document/test/1.py", line 54, in make_trouble
    raise Exception('info')
Exception: info
118.113.1.255


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM