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

全文共1871字,预计学习时长8分钟

图源:unsplash

 

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

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

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

图源:unsplash

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

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

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

装饰器

图源:unsplash

函数是一级对象

在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 问题。

图源:unsplash

重试!

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

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

来一步一步了解代码:

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

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

图源:unsplash

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

用途:

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

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

结果:

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

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

 

图源:unsplash

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

 


推荐阅读专题

留言点赞发个朋友圈

我们一起分享AI学习与发展的干货

编译组:王俊博、刘玲君

相关链接:

https://towardsdatascience.com/are-you-using-python-with-apis-learn-how-to-use-a-retry-decorator-27b6734c3e6

如转载,请后台留言,遵守转载规范

推荐文章阅读

ACL2018论文集50篇解读

EMNLP2017论文集28篇论文解读

2018年AI三大顶会中国学术成果全链接

ACL2017论文集:34篇解读干货全在这里

10篇AAAI2017经典论文回顾

长按识别二维码可添加关注

读芯君爱你

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值