首页 > 编程语言 > 详细

python装饰器实现函数重试

时间:2021-04-06 21:08:07      阅读:27      评论:0      收藏:0      [点我收藏+]

一、介绍

在执行爬虫requests库时,经常会碰到各种的请求失败,有时是超时,有时是代理失败。那么此时我们还是需要拿到数据就必须重试执行几次函数

在代码中就是多来几次函数加括号,或者是来个递归函数,直到执行成功。但还是比较麻烦的。

那么使用装饰器来实现是最好的,需要重试的就加上装饰器,不需要的就不加,这样写代码也更灵活

二、代码

from functools import wraps, partial
import os
import logging
import logging.config as log_conf
import time

log_dir = os.path.dirname(__file__) + /logs
if not os.path.exists(log_dir):
    os.mkdir(log_dir)

log_path = os.path.join(log_dir, retry.log)

log_config = {
    version: 1.0,
    formatters: {
        detail: {
            format: %(asctime)s - %(name)s - %(levelname)s - %(message)s,
            datefmt: "%Y-%m-%d %H:%M:%S"
        },
        simple: {
            format: %(name)s - %(levelname)s - %(message)s,
        },
    },
    handlers: {
        console: {
            class: logging.StreamHandler,
            level: INFO,
            formatter: detail
        },
        file: {
            class: logging.handlers.RotatingFileHandler,
            maxBytes: 1024 * 1024 * 5,
            backupCount: 10,
            filename: log_path,
            level: INFO,
            formatter: detail,
            encoding: utf-8,
        },
    },
    loggers: {
        crawler: {
            handlers: [console, file],
            level: DEBUG,
        },
        parser: {
            handlers: [file],
            level: INFO,
        },
        other: {
            handlers: [console, file],
            level: INFO,
        },
        storage: {
            handlers: [file],
            level: INFO,
        }
    }
}

log_conf.dictConfig(log_config)

r_logger = logging.getLogger(retry)


def retry(times=-1, delay=0, exceptions=Exception, logger=r_logger):
    """
    :param times: 重试次数
    :param delay: 重试间隔时间
    :param exceptions: 想要捕获的错误类型
    :param logger: 指定日志对象输出
    :return: func result or None
    """
    def _inter_retry(caller, retry_time, retry_delay, es):
        while retry_time:
            try:
                return caller()
            except es as e:
                retry_time -= 1
                if not retry_time:
                    logger.error("max tries for {} times, {} is raised, details: func name is {}, func args are {}".
                                 format(times, e, caller.func.__name__, (caller.args, caller.keywords)))
                    raise
                time.sleep(retry_delay)

    def retry_decorator(func):
        @wraps(func)
        def _wraps(*args, **kwargs):
            return _inter_retry(partial(func, *args, **kwargs), times, delay, exceptions)
        return _wraps
    return retry_decorator

三、结果

@retry() #默认无限重试
def get_data():
    print(1)
    res = a + b # 假设函数执行错误
    return res

res = get_data()
print(res)


@retry(5,2) #重试5次,每隔2秒,如果都不成功,就抛出异常
def get_data():
    print(1)
    res = a + b # 假设函数执行错误
    return res

res = get_data()
print(res)

 

python装饰器实现函数重试

原文:https://www.cnblogs.com/angelyan/p/14622270.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!