Python多线程的退出控制实现


Posted in Python onAugust 10, 2020

日常前言

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

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:如下图便只打印了四次

Python多线程的退出控制实现

最后

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

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

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

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

到此这篇关于Python多线程的退出控制实现的文章就介绍到这了,更多相关Python多线程退出控制内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python黑魔法之参数传递
Feb 12 Python
探究python中open函数的使用
Mar 01 Python
pandas.DataFrame选取/排除特定行的方法
Jul 03 Python
详解python 模拟豆瓣登录(豆瓣6.0)
Apr 18 Python
基于Python中的yield表达式介绍
Nov 19 Python
pycharm解决关闭flask后依旧可以访问服务的问题
Apr 03 Python
Django Path转换器自定义及正则代码实例
May 29 Python
Python魔术方法专题
Jun 19 Python
Pytorch框架实现mnist手写库识别(与tensorflow对比)
Jul 20 Python
python爬取招聘要求等信息实例
Nov 20 Python
Python爬虫之Selenium实现关闭浏览器
Dec 04 Python
python matlab库简单用法讲解
Dec 31 Python
Python进行统计建模
Aug 10 #Python
Python如何爬取b站热门视频并导入Excel
Aug 10 #Python
拿来就用!Python批量合并PDF的示例代码
Aug 10 #Python
Python 发送邮件方法总结
Aug 10 #Python
Python getattr()函数使用方法代码实例
Aug 10 #Python
Python matplotlib模块及柱状图用法解析
Aug 10 #Python
Python如何操作docker redis过程解析
Aug 10 #Python
You might like
php cookie 登录验证示例代码
2009/03/16 PHP
php正则表达式(regar expression)
2011/09/10 PHP
php模拟服务器实现autoindex效果的方法
2015/03/10 PHP
PHP实现笛卡尔积算法的实例讲解
2019/12/22 PHP
IE8 兼容性问题(属性名区分大小写)
2009/06/04 Javascript
js和jquery批量绑定事件传参数一(新猪猪原创)
2010/06/23 Javascript
javascript 延迟加载技术(lazyload)简单实现
2011/01/17 Javascript
Json字符串转换为JS对象的高效方法实例
2013/05/01 Javascript
JS获取客户端IP地址、MAC和主机名的7个方法汇总
2014/07/21 Javascript
javascript转换静态图片,增加粒子动画效果
2015/05/28 Javascript
JS实现密码框根据焦点的获取与失去控制文字的消失与显示效果
2015/11/26 Javascript
AngularJS 服务详细讲解及示例代码
2016/08/17 Javascript
利用JS实现点击按钮后图片自动切换的简单方法
2016/10/24 Javascript
Node.js开发第三方微信公众平台
2017/06/05 Javascript
JavaScript全屏和退出全屏事件总结(附代码)
2017/08/17 Javascript
vue.js整合vux中的上拉加载下拉刷新实例教程
2018/01/09 Javascript
layui表格设计以及数据初始化详解
2019/10/26 Javascript
js实现简单的贪吃蛇游戏
2020/04/23 Javascript
JavaScript中展开运算符及应用的实例代码
2021/01/14 Javascript
[49:08]Secret vs VP 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
常用python数据类型转换函数总结
2014/03/11 Python
浅谈Python接口对json串的处理方法
2018/12/19 Python
对python操作kafka写入json数据的简单demo分享
2018/12/27 Python
基于Python实现迪杰斯特拉和弗洛伊德算法
2020/05/27 Python
Pandas之MultiIndex对象的示例详解
2019/06/25 Python
python实现点击按钮修改数据的方法
2019/07/17 Python
解决Python设置函数调用超时,进程卡住的问题
2019/08/08 Python
Python实现的北京积分落户数据分析示例
2020/03/27 Python
美国美食礼品篮网站:Gourmet Gift Baskets
2019/12/15 全球购物
应届生程序员求职信
2013/11/05 职场文书
品牌宣传方案
2014/03/21 职场文书
大二学习计划书范文
2014/04/27 职场文书
趣味运动会简讯
2015/07/20 职场文书
养成教育工作总结
2015/08/13 职场文书
婚礼长辈答谢词
2015/09/29 职场文书
Mysql使用全文索引(FullText index)的实例代码
2022/04/03 MySQL