This article was last updated on <span id="expire-date"></span> days ago, the information described in the article may be outdated.
项目中用到的一个小功能,但是在网上没有找到相关的任何比较好的想法/实现。
自己想到一种 Python 跨平台实现函数执行时间限制的思路。
网上的方法比较多的是利用信号量 signal 设置一个定时器,超时之后执行回调函数,引发 TimeoutError
,退出执行。
这种方法易于实现,并且占用资源少,只需要设置一个 signal.alarm
的闹钟即可。
但是缺点也显而易见:在 Windows 平台 并不能够使用。
分析 signal 的这种方式,我有了一种灵感:让触发退出的回调函数与任务函数 “抢占执行” —— 谁先执行完,就返回谁的值:在计时线程返回之后,不管任务子线程的执行结果,直接返回错误/返回指定值。
threading 库中有一个 Timer 函数,我们用它来计时;在整个过程中,需要同步线程内部的值到父线程/主进程中 —— 最好的选择个人认为还是队列。这里我们不单单将闭包中的队列变量用来同步 return 的值,还可以利用队列一个很好的特性 —— 锁,在任务线程和计时线程均开始运行之后,可以用队列的 get 锁把父线程/主进程阻塞掉,这样既能保证很低的系统占用,又可以实现回收线程返回值的目标(但我这里单独给了一个锁变量控制),一举两得。
下面贴代码:
1 | # author : [email protected] |
如果不想让超时之后引发 TimeoutError,请给装饰器传入 default参数,作为超时之后的默认返回值。
另外需要注意的一点时:任务函数并不会随着装饰器函数的退出而结束,因为在这里父线程是主进程,虽然设置了 Daemon ,但是装饰起函数退出后,主进程仍在执行,便不会退出任务线程(如果一定要退出任务线程,请考虑将整个过程单独出来成为一个线程,但是这样回更多的占用资源,并且需要再次同步父线程和主进程之间的返回值,比较麻烦。)
这样就可以实现跨平台的函数执行时间限制。
Comments