社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python中异常重试解决方案

编程派 • 8 年前 • 898 次点击  

原文:https://www.biaodianfu.com/python-error-retry.html

作者:标点符

全文约 2600 字,读完可能需要 4 分钟。

在做数据抓取的时候,经常遇到由于网络问题导致的程序保存,先前只是记录了错误内容,并对错误内容进行后期处理。

原先的流程:

  1. def crawl_page(url):

  2.     pass

  3.  

  4. def log_error(url):

  5.     pass

  6.  

  7. url = ""

  8. try:

  9.    crawl_page(url)

  10. except:

  11.     log_error(url)

改进后的流程:

  1. attempts = 0

  2. success = False

  3. while attempts < 3 and not success:

  4.     try:

  5.         crawl_page(url)

  6.         success = True

  7.     except:

  8.         attempts = 1

  9.         if attempts == 3:

  10.             break

最近发现的新的解决方案:retrying

retrying 是一个 Python 的重试包,可以用来自动重试一些可能运行失败的程序段。retrying 提供一个装饰器函数 retry,被装饰的函数就会在运行失败的条件下重新执行,默认只要一直报错就会不断重试。

  1. import random

  2. from retrying import retry

  3.  

  4. @retry

  5. def do_something_unreliable():

  6.     if random.randint(0, 10) > 1:

  7.         raise IOError("Broken sauce, everything is hosed!!!111one")

  8.     else:

  9.         return "Awesome sauce!"

  10.  

  11. print do_something_unreliable()

如果我们运行 haveatry 函数,那么直到 random.randint 返回 5,它才会执行结束,否则会一直重新执行。 
retry 还可以接受一些参数,这个从源码中 Retrying 类的初始化函数可以看到可选的参数:

  • stopmaxattempt_number:用来设定最大的尝试次数,超过该次数就停止重试

  •  stopmaxdelay:比如设置成 10000,那么从被装饰的函数开始执行的时间点开始,到函数成功运行结束或者失败报错中止的时间点,只要这段时间超过 10 秒,函数就不会再执行了

  • wait_fixed:设置在两次 retrying 之间的停留时间

  • waitrandommin 和 waitrandommax:用随机的方式产生两次 retrying 之间的停留时间

  • waitexponentialmultiplier 和 waitexponentialmax:以指数的形式产生两次 retrying 之间的停留时间,产生的值为 2^previousattemptnumber * waitexponentialmultiplier,previousattemptnumber 是前面已经 retry 的次数,如果产生的这个值超过了 waitexponentialmax 的大小,那么之后两个 retrying 之间的停留值都为 waitexponentialmax。这个设计迎合了 exponential backoff 算法,可以减轻阻塞的情况。

  • 我们可以指定要在出现哪些异常的时候再去 retry,这个要用 retryonexception 传入一个函数对象:

  1. def retry_if_io_error(exception):

  2.     return isinstance(exception, IOError)

  3.  

  4. @retry(retry_on_exception=retry_if_io_error)

  5. def read_a_file():

  6.     with open("file" , "r") as f:

  7.         return f.read()

在执行 readafile 函数的过程中,如果报出异常,那么这个异常会以形参 exception 传入 retryifio_error 函数中,如果 exception 是 IOError 那么就进行 retry,如果不是就停止运行并抛出异常。

我们还可以指定要在得到哪些结果的时候去 retry,这个要用 retryonresult 传入一个函数对象:

  1. def retry_if_result_none(result):

  2.     return result is None

  3.  

  4. @retry(retry_on_result=retry_if_result_none)

  5. def get_result():

  6.     return None

在执行 getresult 成功后,会将函数的返回值通过形参 result 的形式传入 retryifresultnone 函数中,如果返回值是 None 那么就进行 retry,否则就结束并返回函数值。

其他相关资料:


题图:pexels,CC0 授权。

点击阅读原文,查看更多 Python 教程和资源。



原文
今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/weixin/7jS86J15zq
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/2032
 
898 次点击