Python并行运行subprocess时如何为失败的bash命令添加重试机制
解决方案
要实现失败最多重试3次的逻辑,我们需要对原代码做两个核心调整:一是跟踪每个命令的执行失败次数,二是把执行失败且未达重试上限的命令重新加入待执行队列。
完整可运行代码
import os import subprocess import time NUMBER_OF_PROCESSES = 3 MAX_RETRY = 3 # 单命令最多执行次数,包含首次执行 def run_bash_commands_in_parallel(commands): """ 并行执行bash命令,支持失败重试,单命令最多重试MAX_RETRY次 """ # 待执行队列,每个元素格式为 (命令内容, 已失败次数) pending_tasks = [(cmd, 0) for cmd in commands] # 运行中的进程列表,每个元素格式为 (Popen对象, 对应命令, 已失败次数) running_processes = [] max_processes = NUMBER_OF_PROCESSES while pending_tasks or running_processes: # 第一步:清理已结束的进程,判断是否需要重试 finished = [] for idx, (p, cmd, retry_cnt) in enumerate(running_processes): return_code = p.poll() if return_code is not None: finished.append(idx) if return_code != 0: if retry_cnt < MAX_RETRY - 1: print(f"命令 `{cmd}` 执行失败,返回码{return_code},剩余重试次数{MAX_RETRY - 1 - retry_cnt},重新加入队列") pending_tasks.append((cmd, retry_cnt + 1)) else: print(f"命令 `{cmd}` 累计失败{MAX_RETRY}次,达到上限,不再重试") else: print(f"命令 `{cmd}` 执行成功") # 从运行列表倒序删除已结束的进程,避免索引错乱 for idx in reversed(finished): running_processes.pop(idx) # 第二步:补满运行中的进程数到上限 while pending_tasks and len(running_processes) < max_processes: cmd, retry_cnt = pending_tasks.pop(0) print(f"启动命令:`{cmd}`,第{retry_cnt + 1}次执行") p = subprocess.Popen(cmd, shell=True) running_processes.append((p, cmd, retry_cnt)) # 避免空转占用过高CPU time.sleep(0.1) commands = ['gdalwarp aaaa', 'gdalwarp bbbb', 'gdalwarp ccc'] run_bash_commands_in_parallel(commands)
核心改动说明
- 新增了待执行队列
pending_tasks,存储每个命令和对应的已失败次数,失败后满足条件的命令会重新加入该队列 - 运行中的进程不再仅存储Popen对象,而是绑定对应的命令和已失败次数,方便进程结束后判断是否需要重试
- 新增循环逻辑,只要队列还有待执行任务或者有进程在运行,就持续处理,直到所有任务执行完成或达到重试上限
- 新增重试次数控制,单命令累计失败3次后直接丢弃,不再重试
内容的提问来源于stack exchange,提问作者Bằng Rikimaru
相关产品推荐
相关产品推荐

