Python多线程的退出控制实现

这篇文章主要介绍了Python多线程的退出控制实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

日常前言

最近接 到一个抢票的爬虫外包,那个网站及其之捞,访问购票地址竟然还要排队,在购票高峰临时升一下服务器配置不行吗…没办法,甲方爸爸的要求还得做啊,其中一个障碍便是目标网站的后端限制了访问频次,俗话说:“上有政策,下有对策。” 立刻想到了多线程 + 多代理的方式进行访问。

但此时问题便来了,多代理还好说,再写个爬虫爬一堆下来就好,多线程可就麻烦多了,多线程一旦发出去了,基本等同于失控的状态,你无法去结束或者是重启一个线程,最多只能是获取线程的信息,没有实际的控制权,而且Python官方也没有提供相应的结束函数。那么接下来,让我们来好好聊聊解决这个问题的思路。

单线程的结束

说实话,会百度在程序世界是一个优秀的习惯,不然怎么会有这么一张表情包呢


但是百度这一次却不尽人意,搜了很久,结果不尽人意,基本上所有的搜索结果都告诉我只有结束单个线程的方法,我也试过循环使用百度的结束函数,但最终都只能是结束的当前的这一个线程,无法达到目标。

贴一段搜到的单线程结束代码示例

 def _async_raise(tid, exctype): tid = ctypes.c_long(tid) if not inspect.isclass(exctype): exctype = type(exctype) res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype)) if res == 0: raise ValueError("invalid thread id") elif res != 1: ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None) raise SystemError("PyThreadState_SetAsyncExc failed") def stop_thread(thread): _async_raise(thread.ident, SystemExit) 

那怎么结束多个线程呢?

既然度娘也搜不到,那就自己探索,打开python threading模块的官方文档,其中一个daemon属性进入了视野,单词翻译过来便是守护进程,相信大家应该或多或少的听到过,以下是官方的释义,大概意思就是只要在启动线程之前设置了这个属性为True,当父进程结束时,所有的子进程跟着全部结束,这样就好办了,接下来看看代码部分。

daemon
A boolean value indicating whether this thread is a daemon thread (True) or not (False). This must be set before start() is called, otherwise RuntimeError is raised. Its initial value is inherited from the creating thread; the main thread is not a daemon thread and therefore all threads created in the main thread default to daemon = False.

完整代码

 import threading,time,random class Messy: def __init__(self): self.__messy = 0 def m(self,i): # 随机时间进行打印 time.sleep(random.random()*2) print(i) if i == 1: self.__messy = 1 def main(self): Threads = [] # 将会启动10个线程,线程id为 1 时全部线程终止! for i in range(10): t = threading.Thread(target=self.m,args=(i,)) t.daemon = 1 Threads.append(t) # 启动所有线程 for i in Threads: i.start() # 当标志位【 messy 】时所有多线程结束 while 1: if self.__messy: break print('线程已退出!') Messy().main() # 继续执行后续程序 for i in range(5): print('yeah!') 

此时,main这个函数对于多线程来讲,便是父进程,也就是守护进程。预计会进行10次循环的数字打印,但是当self.__messy这个标志位为真时,所有的剩余子线程将不会再执行,直接结束进行后续的操作

e.g:如下图便只打印了四次

最后

目前来讲,用设置主线程退出的方法是可以完成现在这个抢票的目标。

但是后来发现其实这么做也会带来很多坏处,直接杀掉所有子线程对系统来说是一个很粗鲁的行为,如果涉及到的操作包括了文件数据、数据库数据的改动的话,内存无法被合理释放(之前就遇到过CPU莫名占用满),极有可能造成数据丢失甚至系统中断

我这里只是一个抢票的小程序,子线程只用到了POST,网络请求中断带来的影响还是相对来讲比较小的,所以大家酌情使用本篇所介绍的方法。

本文作者: Messy
原文链接:https://www.messys.top/detail/78

以上就是Python多线程的退出控制实现的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » python