Python retrying 重试机制详解

目录
  • 循环加判断
  • retrying
  • 总结

我们在程序开发中,经常会需要请求一些外部的接口资源,而且我们不能保证每次请求一定会成功,所以这些涉及到网络请求的代码片段就需要加上重试机制。下面来说一下Python中的重试方法。

循环加判断

最简单的重试方式就是在需要进行重试的代码片段上加一个循环,程序内捕获异常,如果执行成功就退出循环,执行失败就就重复执行相关代码,例如:

import requests
def req_with_retry(url):
    retry_max = 10  # 最大重试次数为10次
    for i in range(1, retry_max+1):
        try:
            print("第{}次请求".format(i))
            # 这里请求不到会抛ConnectTimeout异常
            res = requests.get(url, timeout=1)
            data = res.json()
            print("请求成功:", data)
            break
        except requests.exceptions.ConnectTimeout as e:
            continue
# 请求一个不存在的网址
req_with_retry(https://www.hahaha.cn/haha)

执行结果:

由于请求了一个不存在的网址,所以一直在重试,知道达到最大次数10次。但是这样有一定的代码侵入性,在业务逻辑上加入循环判断显得很不美观,别着急,往下看,还有更好的方法。

retrying

retrying是Python的一个第三方库,它提供一个装饰器函数retry,被装饰的业务函数就会在运行失败的条件下重新执行,默认只要报错就会一直重试,直至执行成功。

可以使用pip install retrying进行安装。

例如下面一段代码,我们使用生成随机数的大小的方式模拟业务的成功与失败,只要是生成的随机数大于2,都视为失败,就会重试,直到生成的随机数小于2:

import random
from retrying import retry
@retry
def random_with_retry():
    if random.randint(0, 10) > 2:
        print("大于2,重试...")
        raise Exception("大于2")
    print("小于2,成功!")
random_with_retry()

运行结果如下:

retry还可以接受一些参数,下面是源码中Retrying类的初始化函数中可选的参数:

stop_max_attempt_number:最大重试次数,超过该次数就停止重试

stop_max_delay:最大延迟时间(执行这个方法重试的总时间),超过该时间就停止

wait_fixed:两次retrying之间的等待时间

wait_random_minwait_random_max:用随机的方式产生两次retrying之间的等待时间

wait_incrementing_startwait_incrementing_increment:每调用一次增加固定时长

wait_exponential_multiplierwait_exponential_max:以指数的形式产生两次retrying之间的等待时间,产生的值为2^previous_attempt_number * wait_exponential_multiplierprevious_attempt_number是前面已经retry的次数,如果产生的这个值超过了wait_exponential_max的大小,那么之后两个retrying之间的停留值都为wait_exponential_max

特别需要注意的是retry_on_exception参数,它接收一个函数,用法如下:

# 判断异常
def is_MyError(exception):
    print("判断异常", exception)
    print(isinstance(exception, (ValueError, IOError, ConnectionError)))
    return isinstance(exception, (ValueError, IOError, ConnectionError))
@retry(retry_on_exception=is_MyError)
def random_with_retry():
    """
    随机一个0-10之前的整数,大于2抛异常,小于2成功
    :return:
    """
    if random.randint(0, 10) > 2:
        print("大于2,重试...")
        raise ValueError("大于2")
    print("小于2,成功!")
random_with_retry()

这里retry_on_exception参数的大体思想是:接收一个自定义函数is_MyError,在is_MyError函数里判断了是不是属于ValueError, IOError, ConnectionError这三种异常;random_with_retry()函数如果抛出了异常,会去函数is_MyError()判断返回的是True还是False,如果是True则继续重试,如果是False则立即停止并抛出异常。

还有retry_on_result参数,也是接收一个函数,判断业务函数返回哪些结果时需要重试,思想和retry_on_exception参数类似。

我们可以根据自己的需要进行合理的搭配这些参数,达到我们想要的效果。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

时间: 2021-11-24

python retrying模块的使用方法详解

前言 我们在写爬虫的过程中,经常遇到爬取失败的情况,这个时候我们一般会通过try块去进行重试,但是每次都写那么一堆try块,真的是太麻烦,所以今天就来说一个比较pythonic的模块,retrying. 安装 retrying模块的安装很简单直接用匹配安装即可. pip install retrying retring模块通过装饰器的形式来进行重试操作的,首先我们看一个简单的例子 from retrying import retry @retry(stop_max_attempt_number=

python自动重试第三方包retrying模块的方法

retrying是一个python的重试包,可以用来自动重试一些可能运行失败的程序段,retrying提供一个装饰器函数retry,被装饰的函数就会在运行失败的情况下重新执行,默认只要一直报错就会不断重试. 最近写了一个爬虫,需要连接国外的一个网站,经常出现掉线的情况,自己写了一个自动重连的代码,但感觉不够简洁... 后来就上万能的github,找到了一个第三包,基本能满足我的要求.这个第三方包就是retrying. 我的需求就是每当出现request相关异常的时候,就自动重来,上限连接10次:

Python retrying 重试机制的使用方法

目录 循环加判断 retrying 我们在程序开发中,经常会需要请求一些外部的接口资源,而且我们不能保证每次请求一定会成功,所以这些涉及到网络请求的代码片段就需要加上重试机制.下面来说一下Python中的重试方法. 循环加判断 最简单的重试方式就是在需要进行重试的代码片段上加一个循环,程序内捕获异常,如果执行成功就退出循环,执行失败就就重复执行相关代码,例如: import requests def req_with_retry(url): retry_max = 10 # 最大重试次数为10次

python爬虫URL重试机制的实现方法(python2.7以及python3.5)

应用场景: 状态不是200的URL重试多次 代码比较简单还有部分注释 python2.7实现: # -*-coding:utf-8-*- """ ayou """ import requests def url_retry(url,num_retries=3): print("access!") try: request = requests.get(url,timeout=60) #raise_for_status(),如果

Spring boot使用spring retry重试机制的方法示例

当我们调用接口的时候由于网络原因可能失败,再尝试就成功了,这就是重试机制.非幂等的情况下要小心使用重试. tips:幂等性 HTTP/1.1中对幂等性的定义是:一次和多次请求某一个资源对于资源本身应该具有同样的结果(网络超时等问题除外).也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同. 注解方式使用Spring Retry (一)Maven依赖 <!-- 重试机制 --> <dependency> <groupId>org.springframew

python 重定向获取真实url的方法

楼主在做公司项目的时候遇到url重定向的问题,因此上网简单查找,作出如下结果 由于使用的是语言是python所以以下是python的简单解决方案 http_headers = { 'Accept': '*/*','Connection': 'keep-alive', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116

简单谈谈python的反射机制

对编程语言比较熟悉的朋友,应该知道"反射"这个机制.Python作为一门动态语言,当然不会缺少这一重要功能.然而,在网络上却很少见到有详细或者深刻的剖析论文.下面结合一个web路由的实例来阐述python的反射机制的使用场景和核心本质. 一.前言 def f1(): print("f1是这个函数的名字!") s = "f1" print("%s是个字符串" % s) 在上面的代码中,我们必须区分两个概念,f1和"f1

详解Spring Cloud Zuul重试机制探秘

简介 本文章对应spring cloud的版本为(Dalston.SR4),具体内容如下: 开启Zuul功能 通过源码了解Zuul的一次转发 怎么开启zuul的重试机制 Edgware.RC1版本的优化 开启Zuul的功能 首先如何使用spring cloud zuul完成路由转发的功能,这个问题很简单,只需要进行如下准备工作即可: 注册中心(Eureka Server) zuul(同时也是Eureka Client) 应用服务(同时也是Eureka Client) 我们希望zuul和后端的应用

Spring Cloud 请求重试机制核心代码分析

场景 发布微服务的操作一般都是打完新代码的包,kill掉在跑的应用,替换新的包,启动. spring cloud 中使用eureka为注册中心,它是允许服务列表数据的延迟性的,就是说即使应用已经不在服务列表了,客户端在一段时间内依然会请求这个地址.那么就会出现请求正在发布的地址,而导致失败. 我们会优化服务列表的刷新时间,以提高服务列表信息的时效性.但是无论怎样,都无法避免有那么一段时间是数据不一致的. 所以我们想到一个办法就是重试机制,当a机子在重启时,同个集群的b是可以正常提供服务的,如果有

深度辨析Python的eval()与exec()的方法

Python 提供了很多内置的工具函数(Built-in Functions),在最新的 Python 3 官方文档中,它列出了 69 个. 大部分函数是我们经常使用的,例如 print().open() 与 dir(),而有一些函数虽然不常用,但它们在某些场景下,却能发挥出不一般的作用.内置函数们能够被"提拔"出来,这就意味着它们皆有独到之处,有用武之地. 因此,掌握内置函数的用法,就成了我们应该点亮的技能. 在<Python进阶:如何将字符串常量转为变量?>这篇文章中,

详解Python传入参数的几种方法

Python传入参数的方法有:位置参数.默认参数.可变参数.关键字参数.和命名关键字参数.以及各种参数调用的组合 写在前面 Python唯一支持的参数传递方式是『共享传参』(call by sharing) 多数面向对象语言都采用这一模式,包括Ruby.Smalltalk和Java(Java的引用类型是这样,基本类型按值传递) 共享传参是指函数的各个形式参数获得实参中各个引用的副本:也就是说,函数内部的形参是实参的别名(alias) 这种方案的结果是,函数可能会修改作为参数传入的可变对象,但是无

对Python的多进程锁的使用方法详解

很多时候,我们需要在多个进程中同时写一个文件,如果不加锁机制,就会导致写文件错乱 这个时候,我们可以使用multiprocessing.Lock() 我一开始是这样使用的: import multiprocessing lock = multiprocessing.Lock() class MatchProcess(multiprocessing.Process): def __init__(self, threadId, mfile, lock): multiprocessing.Proces