Python3,异常进阶写法之retrying。

异常进阶写法

  • 1、引言
  • 2、异常进阶写法
    • 2.1 普通写法
      • 2.1.1 追加日志定位异常
      • 2.1.2 增加重试机制
    • 2.2 进阶写法
      • 2.2.1 安装
      • 2.2.1 装饰器retry使用
      • 2.2.2 添加最大次数限制
      • 2.2.3 添加最长重试时间
      • 2.2.4 设置固定重试时间
      • 2.2.4 设置时间重试范围
      • 2.2.5 设置特定异常类型
      • 2.2.6 根据返回值判断是否重试
  • 3、总结

1、引言

小屌丝:鱼哥,最近python的文章写的有点少了!
小鱼:也不算少,只是最近大部分精力都放在全链路压测专栏的文章。
小屌丝:你这全链路压测没拦着你写,但是python文章也不能不更新啊。
小鱼:我凸(艹皿艹 )~ ~ 天天凌晨两点半才去睡觉了,还想我啥时候睡觉…
小屌丝:睡觉归睡觉,但是python文章不能不更新啊。
小鱼:我屮艸芔茻~ ~ 我白天上班,还得加加班,晚上10:30 ~ 凌晨2:30 才有时间写文章,你这是压榨! !
小屌丝:我这是为了妹子~ ~
小鱼:别那妹子做挡箭牌,快说吧,今天遇到啥问题了?
小屌丝:…说实话,最近有个妹子问我,异常有哪些写法!
小鱼:这个问题,问的很好。

关于异常的写法,小鱼最近在面试官的时候,也会经常问到求职者。
但是回答的,有点…不完整吧…
其实关于异常的写法,小鱼整理过一篇《常用断言及异常处理》,只是当时是在编写Web端自动化框架时,整理的,
那篇博文,更多的是python自带的库。
而今天我们要来介绍的,是第三方库–retrying

2、异常进阶写法

2.1 普通写法

2.1.1 追加日志定位异常

我们在通过日志输出,来定位异常是很常见的一种,
例如:

# -*- coding: utf-8 -*-
# @ auth : carl_DJ
# @ time : 2021-11-19

def do_something():
    pass

def  log_error():
    pass

try:
    do_something()
except:
    log_error()

这个写法,也是简单版的异常写法

2.1.2 增加重试机制

增加重试次数,也就是说第一次请求失败,再次发起请求,直到请求成功。
这个一般应用于两种场景:

  • 爬虫
  • 安全测试的攻防演练

我们来看下代码:

# -*- coding: utf-8 -*-
# @ auth : carl_DJ
# @ time : 2021-11-19


def do_something():
    pass

attemps = 0
success = Flase

while attemps < 4  and not success:
    try:
        do_something()
        success = True
    except:
        attemps += 1

        if attemps ==4:
            break

小屌丝:这个写法,不错呢。
小鱼:嗯,跟第一个相比,这个写法,更明确一下,也更高大上一些。
小屌丝:那还有更高大上的写法吗。
小鱼:那必须的,今天主角还没出场呢。

2.2 进阶写法

今天我们来说的这个模块,就是retrying
也是第三方模块,主要是对程序中异常重试的一种优雅的解决方案。

2.2.1 安装

安装方式,老规矩,直接pip安装:

pip install retrying

如果觉得每次都pip install 费时费力,那就看看小鱼这两篇:

Python3,选择Python自动安装第三方库,从此跟pip说拜拜!!》
Python3,我低调的只用一行代码,就导入Python所有库!

2.2.1 装饰器retry使用

retrying模块中,提供了一个装饰器函数retry;
装饰的函数会在运行失败的情况下重新执行,默认一直报错就一直重试,直到成功为止。
我们来看下代码

# -*- coding: utf-8 -*-
# @ auth : carl_DJ
# @ time : 2021-11-19

import  random
from retrying import retry

#retry 装饰器
@retry
def do_something_retry():
    if random.randint(0,10) > 1:
        print(f'this is a test!')
        raise IOError('raise exception!')
    else:
        return "Nice!"

print(do_something_retry())
	

Python3,异常进阶写法之retrying。_第1张图片
小屌丝:为什么每次执行这段,都会打印出不同次数的"this is a test!"

小鱼:这是由于我们程序中只要随机整数大于1就会打印并且抛出异常。
但是由于我们有装饰器函数 retry,所以在发生异常就会重新再次执行方法,直到随机整数大于1,就会打印“Nice!”。
小屌丝:哦,这样啊,那我不想一直这么重试下去,能不能添加点限制之类的呢?
小鱼:嗯,可以的。我们不妨添加最大重试次数为4次。

2.2.2 添加最大次数限制

代码展示

# -*- coding: utf-8 -*-
# @ auth : carl_DJ
# @ time : 2021-11-19

import  random
from retrying import retry

#retry 装饰器添加最大次数限制
@retry(stop_max_attempt_number = 4)
def do_something_times():
    print(f"do something several times")
    raise Exception("raise exception")

do_something_times()
	

小屌丝:真的呢,最多就是4次,那还有别的限制吗?
小鱼:这必须的。

2.2.3 添加最长重试时间

代码展示

# -*- coding: utf-8 -*-
# @ auth : carl_DJ
# @ time : 2021-11-19

from retrying import retry

# 限制最长重试时间(从执行方法开始计算)
@retry(stop_max_delay = 4000)
def do_something_intime():
    print(f"do something in time")
    raise Exception("raise exception")

do_something_intime()
	

2.2.4 设置固定重试时间

代码展示

# -*- coding: utf-8 -*-
# @ auth : carl_DJ
# @ time : 2021-11-19

from retrying import retry

# 设置固定重试时间
@retry(wait_fixed = 3000)
def wait_fixed_time():
    print(f"wait")
    raise Exception("raise exception")

wait_fixed_time()
	

2.2.4 设置时间重试范围

代码展示

# -*- coding: utf-8 -*-
# @ auth : carl_DJ
# @ time : 2021-11-19

from retrying import retry

# 设置重试时间的随机范围
@retry(wait_random_min=1000,wait_random_max=2000)
def wait_random_time():
    print(f"wait")
    raise Exception("raise exception")

wait_random_time()
	

2.2.5 设置特定异常类型

代码展示

# -*- coding: utf-8 -*-
# @ auth : carl_DJ
# @ time : 2021-11-19

from retrying import retry

#根据异常重试
def retry_if_io_error(exception):
	return isinstance(exception, IOError)

# 设置特定异常类型重试
@retry(retry_on_exception=retry_if_io_error)
def retry_special_error():
    print(f"retry io error")
    raise IOError("raise exception")

retry_special_error()
	

在这里,我们自己定义一个函数,判断异常类型,然后将函数作为参数传给装饰函数 retry ,如果异常类型符合,就会进行重试。

2.2.6 根据返回值判断是否重试

代码展示

# -*- coding: utf-8 -*-
# @ auth : carl_DJ
# @ time : 2021-11-19

from retrying import retry

# 通过返回值判断是否重试
def retry_if_result_none(result):
    # return result is None
    if result =="123":
        return True

@retry(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 "123"

might_return_none()
	

这里我们定义了一个判断返回值的函数,然后将这个函数作为参数传给 retry 装饰函数。当结果返回是“123”时,就会一直重试执行 might_return_none 函数。

3、总结

在实际应用中,有的大佬偏向于使用第三方库,而有的大佬,喜欢自带的库。
不管是python自带的库,还是第三方库,在撸码过程中,能直接抛出异常,定位异常,就是最好。
所以,

  • 如果喜欢自带库,那就看这篇:《常用断言及异常处理
  • 如果喜欢第三方库,就看此篇《Python3,异常进阶写法之retrying

你可能感兴趣的:(Python开发实战及代码讲解,python,开发语言,后端)