栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Python中两种多线程实现方式对比

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python中两种多线程实现方式对比

前言

  实习期间需要用到python多线程,先后使用了threading和ThreadPoolExecutor两个模块,因此简单记录一下。

一、使用需求

  公司项目需要增加一个多个设备同时升级的接口,接口接收的参数是多台设备的相关信息,为了提高升级效率,需要开启多线程去做升级操作。

二、ThreadPoolExecutor实现

参考:
  [python] ThreadPoolExecutor线程池
  as_completed函数用例

1. 主要代码
	with ThreadPoolExecutor(max_workers=20) as executor:
	     for device in devices['devices']:
	         device['reboot_dev']=reboot_dev
	         device['testCycleId']=testCycleId
	         device['firmware_type']=firmware_type
	         device['task_id']=str(task_id)
	         task = executor.submit(device_upgrade, **device)
	         task_list.append(task)
	         
	     # #as_completed按完成顺序返回,不按添加顺序遍历
	     # for future in as_completed(task_list):    
	        #     # print("future:",future.__dict__)
	        #     print("result:",future.result())
	        #     if future.result()['success']==False:
	        #         msg_dicts.append(dict(success='False',ip=devices['devices'][index]['ip'],msg=future.result()['msg']))
	        #         flag=False
	        #     else:
	        #         msg_dicts.append(dict(success='True',ip=devices['devices'][index]['ip'],msg=future.result()['msg']))
	        #     index+=1
	        
		 #按添加顺序遍历
	     for future in task_list:    
	         # print("future:",future.__dict__)
	         print("result:",future.result())
	         if future.result()['success']==False:
	             msg_dicts.append(dict(success=False,ip=devices['devices'][index]['ip'],msg=future.result()['msg']))
	             flag=False
	         else:
	             msg_dicts.append(dict(success=True,ip=devices['devices'][index]['ip'],msg=future.result()['msg']))
	         index+=1
2.小结

  concurrent.futures模块使用起来十分简洁方便,ThreadPoolExecutor 是线程池执行者,相较于多开线程能够有更好的效率,不使用as_completed是按添加顺序遍历执行结果,使用as_completed这个生成器,实现先完成先处理,可以进一步提高效率。

三、threading实现

参考:Python中的多线程

1.引入原因

  原本按照ThreadPoolExecutor的方法能够实现多线程,但是由于每次多线程升级时,cpu会跑满,导致FastApi项目自动重启,重启后会接着升级,但此期间接口会返回502,所以利用redis将升级日志存储起来,不等升级完成直接返回结果,新建一个接口去读取redis存储的实时升级日志。
  但是在尝试用下面代码实现时,发现还是会阻塞主线程(也有可能是我使用方法不对):

	with ThreadPoolExecutor(max_workers=20) as executor:
		for device in devices['devices']:
			device['reboot_dev']=reboot_dev
			device['testCycleId']=testCycleId
			device['firmware_type']=firmware_type
			device['task_id']=str(task_id)
			task = executor.submit(device_upgrade, **device)
			task_list.append(task)
	return {"success":True,"msg":"正在升级中..."}

  因此,尝试换种方法来实现,也就是使用threading模块。

2.主要代码
	for device in devices['devices']:
        device['reboot_dev']=reboot_dev
        device['testCycleId']=testCycleId
        device['firmware_type']=firmware_type
        device['task_id']=str(task_id)
        task = threading.Thread(target=device_upgrade, args=(None,device['ip'],device['port'],device['username'],device['password'],device['reboot_dev'],"","","","","","","","",device['testCycleId'],device['firmware_type'],device['task_id']))
        task.start()
        redis_conn.hset(str(task_id), device['ip'], "begin")
        print(device['ip'],"beginning!!!")
        first_log=redis_conn.hget(str(task_id),'log')
        print(first_log)
        if str(first_log)=="None":
            redis_conn.hset(str(task_id),'log',datetime.datetime.strftime(datetime.datetime.now(),'%Y-%m-%d %H:%M:%S')+ " IP:"+device['ip']+" 开始升级n")
        else:
            redis_conn.hset(str(task_id),'log',str(redis_conn.hget(str(task_id),'log'))+datetime.datetime.strftime(datetime.datetime.now(),'%Y-%m-%d %H:%M:%S')+ " IP:"+device['ip']+" 开始升级n") 
    return {"success":True,"msg":"正在升级中..."}
3.小结

  threading模块的实现方法是用一个for循环依次start线程,这样的方法相较于线程池效率会有所降低,但是能够不阻塞主线程,在主线程结束后,子线程依然能够执行下去,能够越过资源不足的问题。

四、总结

  此次实现多线程的两种方式中,主要推荐线程池的方式去执行批量的任务,但是由于我使用线程池的方法无法满足项目需求(有哪位大佬指点一下咋实现),所以换为threading模块实现。
  本次也算是和Python多线程打了交道,感觉自己还是有很多东西不会,继续加油吧。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/976901.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号