Python实现Windows进程耗时监控:超时终止并自动重试
解决方案:Python监控并重启Windows下的商业exe进程
核心疑问解答
- 终止子线程无法关闭商业软件进程:
os.system会启动独立的系统进程,Python线程被终止后,这个系统进程不会随之结束,仍会在后台运行。所以必须直接针对商业exe的进程进行终止操作,而非仅终止Python线程。 - 实时计时监控实现:无需等待线程结束,主线程可以在启动进程后,通过循环检查当前时间与进程启动时间的差值,实时判断是否超时。
具体实现方案
放弃os.system+threading的组合,改用subprocess模块管理进程(能直接获取进程句柄),结合psutil模块(方便追踪子进程)实现超时终止与重试逻辑:
- 依赖安装:先安装psutil(用于进程管理)
pip install psutil
- 代码示例
import subprocess import time import psutil import os BAT_PATH = r"C:\path\to\your\script.bat" BAT_ARGS = ["arg1", "arg2"] # bat需要的参数 TIMEOUT_SECONDS = 30 * 60 # 30分钟超时 RETRY_LIMIT = 5 # 可选:最大重试次数 def kill_exe_processes(exe_name): """终止所有同名的商业exe进程""" for proc in psutil.process_iter(['name']): if proc.info['name'].lower() == exe_name.lower(): try: proc.kill() print(f"已终止进程: {exe_name}") except (psutil.NoSuchProcess, psutil.AccessDenied): pass def run_bat_with_timeout(): """运行bat并监控超时""" # 启动bat进程,非阻塞模式 proc = subprocess.Popen([BAT_PATH] + BAT_ARGS, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) start_time = time.time() while True: # 检查进程是否已结束 if proc.poll() is not None: # 进程正常退出,返回成功 stdout, stderr = proc.communicate() print("任务完成,进程已退出") if stderr: print(f"错误输出: {stderr.decode('gbk')}") return True # 检查是否超时 elapsed_time = time.time() - start_time if elapsed_time > TIMEOUT_SECONDS: print(f"运行超时({elapsed_time/60:.1f}分钟),开始终止进程...") # 先终止bat进程,再终止商业exe进程 try: proc.kill() except psutil.NoSuchProcess: pass # 替换成你的商业exe文件名,比如"business_software.exe" kill_exe_processes("business_software.exe") print("进程已终止,准备重试") return False # 每隔10秒检查一次,避免占用过多CPU time.sleep(10) if __name__ == "__main__": retry_count = 0 while retry_count < RETRY_LIMIT: success = run_bat_with_timeout() if success: break retry_count += 1 print(f"第{retry_count}次重试...") if retry_count >= RETRY_LIMIT: print(f"已达到最大重试次数({RETRY_LIMIT}),任务失败")
关键说明
- subprocess.Popen:替代
os.system,支持非阻塞启动进程,并能获取进程对象进行管理。 - psutil.process_iter:遍历系统进程,精准找到商业exe并终止,确保重启前没有残留进程。
- 超时监控逻辑:通过循环实时计算运行时长,超时后先杀bat进程,再杀exe进程,避免重启报错。
- 重试机制:外层循环控制重试次数,可根据需求调整
RETRY_LIMIT。
替代方案(无psutil)
如果无法安装psutil,可以用Windows自带的taskkill命令终止进程:
def kill_exe_processes(exe_name): os.system(f"taskkill /f /im {exe_name}")
但这种方式不够灵活,无法处理进程不存在的情况,建议优先使用psutil。
内容的提问来源于stack exchange,提问作者AlgoManiac
相关产品推荐
相关产品推荐

