python之retry 及‘@‘符号用作函数修饰符

如果自动化中失败了一次,我们给机会了,成功了就既往不咎。只能说明不够稳定。那么retry该如何写呢?

小明刚开始学爬虫的时候,发现请求有很多时候不能得到正确的返回。他这样写的。

def crawl_page(url):
    pass

def log_error(url):
    pass

url = ""
try:
   crawl_page(url)
except:
    log_error(url)

发现很多时候请求一次,得到的是exception,但是多请求两次,就得到了正确的结果。
于是,改进一下:

attempts = 0
success = False
while attempts < 3 and not success:
    try:
        crawl_page(url)
        success = True
    except:
        attempts += 1
        if attempts == 3:
            break

用一个循环来判断函数是否要多次执行。虽然问题解决了,但是不通用,于是乎,他自己写了个装饰器来实现retry的功能:

def retry(attempt):
    def decorator(func):
        def wrapper(*args, **kw):
            att = 0
            while att < attempt:
                try:
                    return func(*args, **kw)
                except Exception as e:
                    att += 1
        return wrapper
    return decorator


@rety(attempt=3)
def crawl_page(url):
    pass

他发现,这样用起来很顺手,后面又改进了一下,变成了这样。

wait_time = 3
max_retry_times =5
import time

from functools import wraps
def retry_for_errors(errors=Exception, retry_times=max_retry_times,
                     poll_time=wait_time):
    """
    Decorator to retry for multiple errors.

    Example::

        @retry_for_errors(errors=(RuntimeError,NameError))
        def func():
            pass
    """

    assert retry_times > 0, 'retry_times must larger than 0!'

    def wrapper_(func):
        @wraps(wrapped=func)
        def wrapper(*args, **kwargs):
            retry = 1
            while retry <= retry_times:
                try:
                    return func(*args, **kwargs)
                except errors as exc:
                    msg = "Retry for {} for {} time...".format(type(exc).__name__, retry)
                    print(msg)
                    retry += 1

                    if retry > retry_times:
                        raise exc
                    else:
                        time.sleep(poll_time)
        return wrapper
    return wrapper_

可是后来发现,python 中有retry这个库,只要安装就可以了。

pip install 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: an exception or a tuple of exceptions to catch. default: Exception.
    :param tries: the maximum number of attempts. default: -1 (infinite).
    :param delay: initial delay between attempts. default: 0.
    :param max_delay: the maximum value of delay. default: None (no limit).
    :param backoff: multiplier applied to delay between attempts. default: 1 (no backoff).
    :param jitter: extra seconds added to delay between attempts. default: 0.
                   fixed if a number, random if a range tuple (min, max)
    :param logger: logger.warning(fmt, error, delay) will be called on failed attempts.
                   default: retry.logging_logger. if None, logging is disabled.
    """

直接调用就可以了,不需要重复造轮子。

真是磨刀不误砍柴工阿!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值