Python出错重试:retrying

在编写Python代码进行自动化测试、网络爬虫或者其他与网络相关的动作的时候,由于网络影响会容易失败,而这种失败并不是我们需要去处理的。那么这种时候最好的办法就是失败后重试几次,以避免网络的间断性影响。

如果我们正常编写代码的话,可能需要 try...except ,但是这种写法很麻烦,能实现的效果也很单一。这里介绍一个 Python 库retrying,专门用来对抛出异常的函数或者方法进行重试。

通过 retrying 你能干什么:

  • 出错后重新运行函数,直到正常运行为止;
  • 出错后,暂停一会再运行函数,因为网络可能一时半会不会好;
  • 出错后,如果重试时间过长,会造成代码效率过低,你可以设置一个最大的重试时间;
  • 出错时,你可能想去执行另一个函数以排除可能的错误。

那接下来我们看看用法,首先你需要安装这个库:

pip install retrying

简单用法

简单的示例,我们写一个函数,其中有一个变量 a 从 1 到 2 中随机取一个, 当 a 为 1 的时候就抛出异常,我们尝试在抛出异常时会不会重试:

import random
def demo():
    a = random.randint(1,2)
    print(a)  # => 先打印,好看效果
    if a == 1:
        raise  # 为1时抛出异常

这个函数有 50% 的概率会抛出错误,你可以先试试。不过如果你运气好的话。。。

好,接下来,我们加上 retrying :

from retrying import retry  # => 引入retry装饰器
import random

@retry()  # => 装饰你想重试的函数,注意这里有括号
def demo():
    a = random.randint(1,2)
    print(a)  # => 先打印,好看效果
    if a == 1:
        raise  # 为1时抛出异常

demo()   # => 运行这个可能报错的函数

运行几次看看,是不是当打印 a 为 1 的时候会直到 a 为 2 为止?也就意味着@rery() 处理了异常并重试。

更多参数

也许你不满足于让它默认重试,那么我们来看看更多的函数。

重试次数

stop_max_attempt_number 最大重试次数,默认为5次

设定一个最大重试次数,超过这个次数会停止重试,并把异常抛出来。按照你的需要设置吧,一般不要太多就行。或者你也可以不设,默认为 5 次,不过前提时你修复了下面的bug。

import random
from retrying import retry

@retry(stop_max_attempt_number=3)
def demo():
    a = random.randint(1,2)
    print(a, end=" ")  # 为了排版,打印横排
    if a != 3:  # => 这里我们改为会始终抛异常的情况,不可能取到3
        raise
demo()
## 1 1 1
## RuntimeError: No active exception to reraise

我们可以看到,运行 3 次都报错后,第 3 次运行的异常就抛出了。

这里源代码有个 bug,如果不设这个参数会无限重试(如果你的异常不会中止就是死循环)。我们来修复这个 bug 😋:

打开 Python安装目录\Lib\site-packages\retrying.py,找到第87

if stop_max_attempt_number is not None:
# 改为
if self._stop_max_attempt_number is not None:

时间相关

wait_fixed 重试的间隔时间

当函数抛出异常后,下一次重试会间隔wait_fixed设置的时间。默认是 1000 毫秒(1秒),你可以通过这个参数修改这个默认值。

wait_random_minwait_random_max 用来设置随机的间隔时间

wait_random_min 和 wait_random_max 搭配起来设置默认的随机等待时间,默认是 0 ~ 1000 毫秒之间随机等待。

wait_incrementing_increment 每重试一次,持续增加等待时间
默认是 100 毫秒 ,每重试一次,等待时常就会增加 100 毫秒。

stop_max_delay 最长重试延迟时间,单位毫秒

这个不是重试间隔时间,这是函数运行 + 重试结束的整体时间。比如stop_max_delay=2000也就是说该函数从运行到重试结束为止的时间为 2000 毫秒,超过就结束重试并抛出异常。如果你的函数运行时间已经超过 stop_max_delay 时间,就并不会重试。

import time
import random
from retrying import retry

@retry(stop_max_delay=2000)  # => 设置了最大的重试时间
def demo():
    a = random.randint(1, 2)
    print(a, end=" ")
    time.sleep(1)  # => 这里等待了1秒
    if a != 3:
        raise
demo()
## 1 2 
## RuntimeError: No active exception to reraise

关联函数重试

retry_on_result:指定一个函数,如果指定的函数返回True,则重试,否则抛出异常退出。

import random
from retrying import retry

def fun():
    # 处理代码
    return True  # => 返回True

@retry(retry_on_result=fun) # 指定函数,如果fun返回True则重试,否则不重试
def demo():
    a = random.randint(1, 2)
    print(a, end=" ")
    if a != 3:
        raise
demo()

shop_func:指定被装饰函数出错后,会执行的函数,执行该函数后在来重试被装饰的函数。注意,该函数必须要有两个参数(attempts, delay)。用来当抛出异常后,需要做一些处理的时候。

a = random.randint(1, 2)

def fun(attempts, delay):
    global a
    a = 3
    print('待测函数')

@retry(stop_func=fun)
def demo():
    print(a, end=" ")
    time.sleep(1)
    if a != 3:
        raise
demo()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容