最近在做爬虫使用requests, 爬虫常常在运行一段时间后假死. 而且使用原生协程编写感觉语法也很不方便. 于是翻阅了一些相关文章API之类的. 最后做了如下处理来处理.
大致测试代码如下
import gevent
import time
import random
def setter(i):
sl = random.randint(1, 10)
gevent.sleep(sl)
print("setter%d sleep %d s end time %f"%(i, sl, time.time()))
return "setter%d"%i
def waiter(i):
print("print in waiter %d time %f"%(i, time.time()))
# print(a.get())
return "waiter"
x = []
t = []
# timeout = gevent.Timeout(3, False)
# timeout.start()
# try:
with gevent.Timeout(3, False) as timeout:
for i in range(10):
t.append(gevent.spawn(setter, i))
# x = gevent.joinall(t, timeout=2, raise_error=False)
x = gevent.joinall(t)
# except:
# pass
t2 = time.time()
print("end t1 %f"%time.time())
for g in t:
print("return %s, %f"%(g.get(), time.time()))
print('t2=%f'%t2)
代码中有3种超时设置
第一种:
timeout = gevent.Timeout(2, False)
timeout.start()
这种设置方式, 设为True时超时会直接跑出异常,
设为False时会正常退出管理, 但是其他依然会按顺序执行.
---->关键是. 不执行完所有协程(即使是超时的) 是不会到后面去的. 就是说一个协程假死程序就死了.
---->第一种和第二种情况. x都没有值, x=[], 只有第三种情况可以获取到值. 但是如果不打印t的值的话. 超时后python直接退出了. 所以也有可能是因为后续获取t值实际上干扰了资源分配逻辑. 此处暂不考虑这种情况. 尽量使用由gevent管理的协程.
第二种:
with gevent.Timeout(3, True) as timeout: for i in range(10): t.append(gevent.spawn(setter