python并发——多进程中的异常捕获
在正常的python多进程中,父进程只负责将任务分发给子进程,子进程成功与否,父进程并不关心.
但是在生产环境中,这种显然是不恰当的.通过研究我发现通过回调方法可以获取子进程的状态,然后通过一个queue将失败的子进程标记出来,就可以实现失败进程的重试,代码如下:
import queue import random import time from multiprocessing import Pool q = queue.Queue() success_count = 0 #实际运行的task方法 def long_time_task(table_name): rd = random.randint(1, 10)
#任务失败抛出异常,抛出的就是任务名称,在回调方法中可以捕获 if rd % 2 == 0: raise Exception(table_name) global q print('ok=%s' % table_name) time.sleep(1) #成功任务计数 def success(suc): global success_count success_count = success_count + 1 #失败任务捕获 def err(error): q.put(error) if __name__ == '__main__':
#初始化一个4个槽位线程池 p = Pool(4) lists = ['table_' + str(i) for i in range(1, 21)] lists_num=len(lists)
#将任务放入队列 for i in lists: q.put(i)
#队列为空不一定就是所有任务完成了,可能还有在运行中的任务,所以需要两个条件满足才能退出循环 while not q.empty() or success_count!=lists_num: if q.empty(): time.sleep(1) else: p.apply_async(long_time_task, args=(q.get(),), callback=success, error_callback=err) p.close() p.join() print('q.size=%d,success_count=%d' % (q.qsize(), success_count))
上面的例子有时候是能运行的,但有时候不能,特别是子程序执行很快的时候while经常陷入死循环,原因是
多进程中q.empty()不可信,异步过程中在分发任务时success_count无法获取最终结果,会导致死循环,调整后的程序如下
import os import time from multiprocessing import Pool from multiprocessing import Queue import random q = Queue() success_count = 0 # 通过回调捕获异常 def err(error): q.put(error) def suc(success): global success_count success_count = success_count + 1 def run_data_x(sub_table_name): result = os.system("echo {sub_table_name} 2".format(sub_table_name=sub_table_name)) time.sleep(0.1) if result != 0 or random.randint(1, 100) == 9: print('failed!!!,tb=%s' % sub_table_name) raise Exception(sub_table_name) if __name__ == '__main__': p = Pool(3) table_list = ['test_0', 'test_1', 'test_2', 'test_3', 'test_4', 'test_5', 'test_6', 'test_7', 'test_8', 'test_9', 'test_10', 'test_11', 'test_12', 'test_13', 'test_14', 'test_15'] table_list_num = len(table_list) for tb in table_list: q.put(tb) print('*********************************') # 多进程中q.empty()不可信,异步过程中success_count在分发任务时尚无法获取最终结果,会导致死循环 # 调整为同步获取结果即可 while success_count != table_list_num: # p.apply_async(run_data_x, args=(q.get(),), callback=suc, error_callback=err) try: p.apply(run_data_x, args=(q.get(True),)) suc(1) except Exception as e: err(e) p.close() p.join() print('success_count=%d' % success_count)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗