小编给大家分享一下退出python多线程爬虫的方法有哪些,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧!

解决方案 · 壹

一个比较nice的方式就是每个线程都带一个退出请求标志,在线程里面间隔一定的时间来检查一次,看是不是该自己离开了!

importthreadingclassStoppableThread(threading.Thread):"""Threadclasswithastop()method.Thethreaditselfhastocheckregularlyforthestopped()condition."""def__init__(self):super(StoppableThread,self).__init__()self._stop_event=threading.Event()defstop(self):self._stop_event.set()defstopped(self):returnself._stop_event.is_set()

在这部分代码所示,当你想要退出线程的时候你应当显示调用stop()函数,并且使用join()函数来等待线程合适地退出。线程应当周期性地检测停止标志。

然而,还有一些使用场景中你真的需要kill掉一个线程:比如,当你封装了一个外部库,但是这个外部库在长时间调用,因此你想中断这个过程。

解决方案 · 貳

接下来的方案是允许在python线程里面raise一个Exception(当然是有一些限制的)。

def_async_raise(tid,exctype):'''Raisesanexceptioninthethreadswithidtid'''ifnotinspect.isclass(exctype):raiseTypeError("Onlytypescanberaised(notinstances)")res=ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,ctypes.py_object(exctype))ifres==0:raiseValueError("invalidthreadid")elifres!=1:#"ifitreturnsanumbergreaterthanone,you'reintrouble,#andyoushouldcallitagainwithexc=NULLtoreverttheeffect"ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,0)raiseSystemError("PyThreadState_SetAsyncExcfailed")classThreadWithExc(threading.Thread):'''Athreadclassthatsupportsraisingexceptioninthethreadfromanotherthread.'''def_get_my_tid(self):"""determinesthis(self's)threadidCAREFUL:thisfunctionisexecutedinthecontextofthecallerthread,togettheidentityofthethreadrepresentedbythisinstance."""ifnotself.isAlive():raisethreading.ThreadError("thethreadisnotactive")#dowehaveitcached?ifhasattr(self,"_thread_id"):returnself._thread_id#no,lookforitinthe_activedictfortid,tobjinthreading._active.items():iftobjisself:self._thread_id=tidreturntid#TODO:inpython2.6,there'sasimplerwaytodo:self.identraiseAssertionError("couldnotdeterminethethread'sid")defraiseExc(self,exctype):"""Raisesthegivenexceptiontypeinthecontextofthisthread.Ifthethreadisbusyinasystemcall(time.sleep(),socket.accept(),...),theexceptionissimplyignored.Ifyouaresurethatyourexceptionshouldterminatethethread,onewaytoensurethatitworksis:t=ThreadWithExc(...)...t.raiseExc(SomeException)whilet.isAlive():time.sleep(0.1)t.raiseExc(SomeException)Iftheexceptionistobecaughtbythethread,youneedawaytocheckthatyourthreadhascaughtit.CAREFUL:thisfunctionisexecutedinthecontextofthecallerthread,toraiseanexcpetioninthecontextofthethreadrepresentedbythisinstance."""_async_raise(self._get_my_tid(),exctype)

正如注释里面描述,这不是啥“灵丹妙药”,因为,假如线程在python解释器之外busy,这样子的话终端异常就抓不到啦~

这个代码的合理使用方式是:让线程抓住一个特定的异常然后执行清理操作。这样的话你就能终端一个任务并能合适地进行清除。

解决方案 · 叁

假如我们要做个啥事情,类似于中断的方式,那么我们就可以用thread.join方式。

join的原理就是依次检验线程池中的线程是否结束,没有结束就阻塞直到线程结束,如果结束则跳转执行下一个线程的join函数。

先看看这个:

1. 阻塞主进程,专注于执行多线程中的程序。

2. 多线程多join的情况下,依次执行各线程的join方法,前头一个结束了才能执行后面一个。

3. 无参数,则等待到该线程结束,才开始执行下一个线程的join。

4. 参数timeout为线程的阻塞时间,如 timeout=2 就是罩着这个线程2s 以后,就不管他了,继续执行下面的代码。

#coding:utf-8#多线程joinimportthreading,timedefdoWaiting1():print'startwaiting1:'+time.strftime('%H:%M:%S')+"\n"time.sleep(3)print'stopwaiting1:'+time.strftime('%H:%M:%S')+"\n"defdoWaiting2():print'startwaiting2:'+time.strftime('%H:%M:%S')+"\n"time.sleep(8)print'stopwaiting2:',time.strftime('%H:%M:%S')+"\n"tsk=[]thread1=threading.Thread(target=doWaiting1)thread1.start()tsk.append(thread1)thread2=threading.Thread(target=doWaiting2)thread2.start()tsk.append(thread2)print'startjoin:'+time.strftime('%H:%M:%S')+"\n"forttintsk:tt.join()print'endjoin:'+time.strftime('%H:%M:%S')+"\n"

默认join方式,也就是不带参,阻塞模式,只有子线程运行完才运行其他的。

1、 两个线程在同一时间开启,join 函数执行。

2、waiting1 线程执行(等待)了3s 以后,结束。

3、waiting2 线程执行(等待)了8s 以后,运行结束。

4、join 函数(返回到了主进程)执行结束。

这里是默认的join方式,是在线程已经开始跑了之后,然后再join的,注意这点,join之后主线程就必须等子线程结束才会返回主线。

join的参数,也就是timeout参数,改为2,即join(2),那么结果就是如下了:

两个线程在同一时间开启,join 函数执行。

wating1 线程在执行(等待)了三秒以后,完成。

join 退出(两个2s,一共4s,36-32=4,无误)。

waiting2 线程由于没有在 join 规定的等待时间内(4s)完成,所以自己在后面执行完成。

看完了这篇文章,相信你对退出python多线程爬虫的方法有哪些有了一定的了解,想了解更多相关知识,欢迎关注亿速云行业资讯频道,感谢各位的阅读!