在 Linux/Mac 下为Python函数添加超时时间的方法
我们在使用requests这类网络请求第三方库时,可以看到它有一个参数叫做timeout,就是指在网络请求发出开始计算,如果超过timeout还没有收到返回,就抛出超时异常。(当然存在特殊情况timeout会失效,请看Timeoutsandcancellationforhumans*这篇文章中作者的举例,我们不考虑这种特殊情况)。
但大家有没有考虑过,如何为普通的函数设置超时时间?特别是在运行一些数据处理、AI相关的代码时,某个函数可能会运行很长时间,我们想实现,在函数运行超过特定的时间时,自动报错。
例如有这样一个场景,我写了一个函数calc_statistic(datas),根据用户传入的数据计算某个值。但如果用户传入的数据非常大,这个函数就可能运行很长时间。我想设置让这个函数最多运行10秒钟。如果10秒还没有运行完成,就报错。应该怎么办呢?
如果你的电脑操作系统是Linux或者macOS,那么可以使用signal来解决。
在公众号前几天的文章中,我们介绍了使用signal来接管键盘的中断信号,用到的是signal.SIGINT。今天我们要用到的是signal.SIGALRM。
首先我们来看看这个信号的使用方法:
importtime importsignal defhandler(signum,_): print('定时到!') raiseException('定时到了!') defclac_statistic(datas): time.sleep(100) signal.signal(signal.SIGALRM,handler) signal.alarm(5) clac_statistic('xxx')
运行效果如下图所示:
首先绑定signal.SIGALRM事件到handler函数中,然后使用signal.alarm(10)延迟10秒发送一个信号。10秒到了以后,函数handler被运行。在函数中抛出了一个异常,导致程序结束。clac_statistic函数原本要运行100秒,但是在10秒以后就停止了,从而实现了函数的超时功能。
基于以上原理,我们实现一个装饰器,来简化为不同函数设置超时功能:
importtime importsignal classFuncTimeoutException(Exception): pass defhandler(signum,_): raiseFuncTimeoutException('函数定时到了!') deffunc_timeout(times=0): defdecorator(func): ifnottimes: returnfunc defwraps(*args,**kwargs): signal.alarm(times) result=func(*args,**kwargs) signal.alarm(0)#函数提前运行完成,取消信号 returnresult returnwraps returndecorator signal.signal(signal.SIGALRM,handler)
我们来试一试测试一下这个函数超时装饰器。首先测试函数的运行时间小于超时时间时,程序正常运行没有问题:
再来测试一下函数运行时间超过超时时间的情况:
正常抛出FuncTimeoutException异常。
那我们在实际使用中,可以使用try...exceptFuncTimeoutException捕获这个异常,然后实现自定义的处理流程,例如:
try: clac_statistic(100) exceptFuncTimeException: print('该函数运行超时,运行自定义的处理流程')
当然你如果想直接跳过这个异常也没问题:
importcontextlib: withcontextlib.supress(FuncTimeException): clac_statistic(100)
总结
以上所述是小编给大家介绍的在Linux/Mac下为Python函数添加超时时间的方法,希望对大家有所帮助,也非常感谢大家对毛票票网站的支持!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。