您现在的位置是:首页 > 文章详情

没人想被这些事搞砸!重试装饰器助你一臂之力

日期:2020-04-20点击:377

云栖号资讯:【点击查看更多行业资讯
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!

image

“胶水语言”,顾名思义,意味着这种语言有助于将连接系统,确保数据能以所需结构和格式,由A转到B。Python就是知名度最高的一种胶水语言。笔者曾用Python构建了无数的ETL脚本(数据提取、转换和加载)。

这些脚本基本上都按照相同规则运行。从某处提取数据,数据转化,然后运行最后一步——将数据上传到某个地方,但也可能是有条件的删除。

越来越多的传统公司的基础设施正在被上传到云端,越来越多的公司正在向微服务方式转型。这也意味着一种情况出现的可能大大增加:必须从某个地方提取数据,或从非本地计算机处写入数据。

image

小规模的操作很少出问题。如果某些提取或者回写失败,通常会被注意到,且错误能被纠正。

但如果操作规模更大,并存在成百上千的可能事项时,就会出现暂时中断的网络连接、过多的并发写入、暂时没有相应的源系统或者其他莫名其妙的问题,而没人想被这些事情搞砸。而笔者发现了一个非常简单的重试装饰器,它能解决这些问题。

笔者在大多数项目中都会在某个功能模块中使用重试装饰器,可谓是“大救星”。快来看看吧!

装饰器

image

函数是一级对象

在Python中,函数是一级对象。函数和其他任何对象一样。这一事实意味着函数可以动态创建、传递给函数本身,甚至可以更改。下面这个示例尽管很傻但确是事实:

def my_function(x): print(x)IN: my_function(2) OUT: 2IN: my_function.yolo = you live only once print(my_function.yolo) OUT: you live only once 

修饰语法

为了方便开发人员,Python提供了一种特殊的语法。还可以按如下方式操作:

@convert_to_numeric def first_func(x): return x**2 

以上的语法等同于:

def first_func(x): return x**2first_func =convert_to_numeric(first_func) 

这种语法使实际运行情况更清楚,尤其是在使用多个装饰器的情况下。

修饰函数

可以用另一个函数包装一个函数来满足特定需求,这一点很有用。例如,可以确保函数在被调用时向某个日志端点报告,打印出参数,实现类型检查、预处理或后处理,以列出一些可能性。以下为一个简单示例:

def first_func(x): return x**2 def second_func(x): return x - 2 

当用字符串 2 调用这两个函数时,其都会无法工作。可在其中使用一个类型转换函数,并且用其修饰first_func 和 second_func 。

def convert_to_numeric(func): # define a function within the outerfunction def new_func(x): return func(float(x)) # return the newly defined function return new_func 

这个convert_to_numeric 包装函数需要用一个函数作为参数,并返回另一个函数。现在,虽然先前无法工作,但是如果包装了函数,然后用一个字符串号调用,所有的函数都能按设置的使用。

IN: new_fist_func = convert_to_numeric(first_func)############################### convert_to_numeric returns this function: def new_func(x): return first_func(float(x)) ###############################new_fist_func( 2 ) OUT: 4.0IN: convert_to_numeric(second_func)( 2 ) OUT: 0 

这是为什么?

convert_to_numeric接受一个函数(A)作为参数并返回一个新函数(B)。新函数(B)在被调用时调用函数(A),但它不是用传递的参数x调用函数(A),而是用float(x)调用函数(A),从而解决了以前的TypeError 问题。

image

重试!

基本知识已经介绍完了,现在讲一讲笔者最喜欢的retry装饰器:

image

包装已经包装的函数。是一些初始阶段的内容,这并不复杂!

来一步一步了解代码:

1.最外层函数retry:这将参数化修饰器,即要处理的异常是什么,尝试的频率是多少,两次尝试之间等待的时间是多长,以及指数退避因子是什么(即每次失败时,用什么数字乘以等待时间)。

2.retry_decorator:这是参数化的装饰器,由retry函数返回。用@wraps来修饰retry_decorator中的函数。严格来讲,这在功能上是不必要的。这个包装器更新了包装函数的 namedoc (如果不这样做,函数的 name 始终是 func_with_retries)。

image

3.func_with_retries应用重试逻辑。此函数包装了try-except语句块中的函数调用,并实现指数退避等待和一些日志记录。

用途:

image

函数用重试装饰器修饰,在异常上最多重试四次。或者更具体一点:

image

用在TimeoutError上的重试装饰的函数最多重试两次。

结果:

调用修饰函数,并遇到错误,将会导致如下结果:

image

调用的函数在ConnectionRefusedError上失败两次,在ConnectionResetError上失败一次,在第四次尝试时成功。这里有良好的日志记录,打印了args和kwargs以及函数名,使调试和修复问题变得轻而易举(如果重试次数用完错误依然存在)。

image

了解装饰器如何在Python中工作,以及如何用一个简单的重试装饰器来修饰关键任务函数,这非常有必要的。它是面对不确定情况时的“大救星”!

【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:https://yqh.aliyun.com/zhibo

立即加入社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK

原文发布时间:2020-04-20
本文作者:读芯术
本文来自:“读芯术公众号”,了解相关信息可以关注“读芯术

原文链接:https://yq.aliyun.com/articles/756506
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章