Python Multiprocessing.Process偶发不调用目标函数问题排查求助
问题描述
每日运行的脚本在启动100+个进程时,偶尔会随机出现2-3个进程未启动、目标函数未被调用的情况。该问题近期才出现,此前运行正常,无固定规律,随机某天出现且失败进程数不固定。
成功运行时,日志会包含所有进程的调用记录(顺序不同);异常时会缺失部分进程的调用日志,比如缺少“Process 9 invoker called.”。已尝试在invoker函数中添加日志、记录进程启动前后的细节,寻求进一步排查方向。
现有实现代码
class Worker: def __init__(self, count, file): self.file = file self.count = count def invoker(a): print("Process [self.count] invoker called") for i in range(5): worker = Worker(i, file). # Different worker obj for every different process process = multiprocessing.Process(target=worker.invoker, args=(a, )) proc_list.append(process) proc_list[-1].start() [proc.join() for proc in proc_list]
代码中的明显问题
Worker.invoker作为实例方法,未定义self参数,调用时会触发参数不匹配异常,导致进程启动后直接退出,无法执行打印逻辑。正确定义应为:def invoker(self, a): print(f"Process [{self.count}] invoker called")- 实例化
Worker时多了一个句号(worker = Worker(i, file).),属于语法错误,实际运行的代码应该已修正,否则脚本无法执行。 print语句未做字符串格式化,会输出字面量[self.count]而非实际进程编号,影响日志排查准确性。
排查方向
1. 系统层面进程启动限制排查
- 检查进程数限制:用
ulimit -u查看当前用户最大进程数,cat /proc/sys/kernel/pid_max查看系统全局进程上限。接近或达到上限时,系统会拒绝创建新进程,此时start()会抛出OSError,需添加异常捕获记录失败信息:try: proc_list[-1].start() print(f"Process {i} started, PID: {proc_list[-1].pid}") except OSError as e: print(f"Failed to start process {i}: {str(e)}") - 检查系统资源与日志:异常发生当天,查看CPU、内存、磁盘IO峰值,结合
/var/log/messages或dmesg排查是否有OOM(内存不足)杀死进程的记录;用journalctl或syslog查看fork系统调用失败的日志。
2. 进程内部异常排查
- 完善
invoker日志与异常捕获:记录进程PID、启动/结束时间,捕获所有异常避免静默退出:import logging from multiprocessing import current_process def invoker(self, a): pid = current_process().pid logging.info(f"Process [{self.count}] (PID: {pid}) started") try: # 业务逻辑代码 pass except Exception as e: logging.error(f"Process [{self.count}] (PID: {pid}) failed: {str(e)}", exc_info=True) finally: logging.info(f"Process [{self.count}] (PID: {pid}) finished") - 检查进程状态与退出码:
join()后查看进程退出码,非0表示异常退出,-9通常意味着被系统杀死:for idx, proc in enumerate(proc_list): proc.join() if proc.exitcode != 0: print(f"Process {idx} exited with code: {proc.exitcode}")
3. 运行环境变化排查
- 核对近期环境变更:包括操作系统、Python版本、依赖库更新,以及脚本本身的修改,排查是否引入兼容性或资源占用问题。
- 检查同期运行任务:确认异常当天是否有其他高资源占用的定时任务同时运行,导致系统资源不足。
4. 进程启动方式优化
- 分散进程创建压力:在
start()调用之间添加微小延迟(如time.sleep(0.01)),避免短时间内创建大量进程导致系统瞬时负载过高。 - 使用进程池管理:用
multiprocessing.Pool或concurrent.futures.ProcessPoolExecutor替代手动创建进程,自动管理进程生命周期,控制并发数避免资源过载。
内容的提问来源于stack exchange,提问作者Karan Verma
相关产品推荐
相关产品推荐

