Python3,异常进阶写法之retrying。

举报
Carl_奕然 发表于 2023/05/19 16:41:40 2023/05/19
【摘要】 又涨知识了。

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 费时费力,那就看看小鱼这两篇:

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())


    


小云:为什么每次执行这段,都会打印出不同次数的"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》

我是小鱼:

  • CSDN 博客专家;
  • 阿里云 专家博主;
  • 51CTO 博客专家;
  • 51认证讲师;
  • 金牌面试官;
  • 职业规划师

关注我,带你学习更多更有趣的Python知识。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。