0 问题引入
最近写了爬虫并封装成了一个实时服务api接口,但是爬虫需要大概20s-30s才能完成,而且超时造成的失败也不能很快的反馈给客户端。
通过查看一些资料和与他人讨论有以下几种方式可以解决这个问题:
- 启动两个线程,爬虫任务放在一个线程里,定时任务放在一个线程里,如果时间达到,则终止爬虫任务线程
- 利用信号量机制+装饰器模式来实现定时,而不用改变原有函数。
第一种方法没有找到线程停止的方法所以也没有深入考虑。最后决定尝试第二种方法
1 信号量机制的坑
在python里使用信号量需要引入内置的signal
包,但是信号量机制是依托于操作系统的,所以网上一些示例代码在windows环境下运行会报错!!!。
所以代码的调试必须转动Linux下,为了不(bu)重复(xie)造轮子(daima),这里要隆重介绍超时装饰器包timeout-decorator
。
2 timeout-decorator包
观察了timeout-decorator
包的定时器实现,发现也是基于装饰器和信号量机制实现。
- 安装
pip install timeout-decorator
- 使用示例1:
import time
import timeout_decorator
@timeout_decorator.timeout(3)
def mytest():
time.sleep(5)
return 5
mytest()
上面的代码超时设置为3s,运行后会抛出TimeoutException。
- 使用示例2:
默认情况下,timeout_decorator
运用信号量来限制给定函数的执行时间。如果你的函数不是在main
线程中(例如是一个web应用的worker
线程)执行,那么这个方法就不行了。对这种情况有一个替代的超时策略---通过使用多进程。为了使用它,只要将use_signals=False
添加到timeout decorator
函数中。
import time
import timeout_decorator
@timeout_decorator.timeout(3, use_signals=False)
def mytest():
time.sleep(5)
return 5
mytest()
在其他地方使用超时函数时记得要加上try except
语句捕获异常并做相应处理
网友评论
mytest()
except timeout_decorator.timeout_decorator.TimeoutError:
print('timeout')