You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现Windows进程耗时监控:超时终止并自动重试

解决方案:Python监控并重启Windows下的商业exe进程

核心疑问解答

  • 终止子线程无法关闭商业软件进程:os.system会启动独立的系统进程,Python线程被终止后,这个系统进程不会随之结束,仍会在后台运行。所以必须直接针对商业exe的进程进行终止操作,而非仅终止Python线程。
  • 实时计时监控实现:无需等待线程结束,主线程可以在启动进程后,通过循环检查当前时间与进程启动时间的差值,实时判断是否超时。

具体实现方案

放弃os.system+threading的组合,改用subprocess模块管理进程(能直接获取进程句柄),结合psutil模块(方便追踪子进程)实现超时终止与重试逻辑:

  1. 依赖安装:先安装psutil(用于进程管理)
pip install psutil
  1. 代码示例
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 21:03:30