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

如何并行运行Python子进程以监控并终止外部程序?

解决Python中并行运行外部程序与监控脚本的问题

问题根源

你之前的两种方法失败的原因:

  • 连续使用subprocess.call:call是阻塞式调用,会等待第一个进程(program 1)完全结束后才会启动第二个监控脚本,但program 1无法自行终止,导致监控脚本永远无法运行。
  • 直接用Popen创建进程列表:虽然启动了两个并行进程,但监控脚本无法获取program 1的进程ID(PID),也就无法在检测完成后终止它;且未做后续的进程存活检查,可能主脚本退出后监控进程也被意外终止。

解决方案

方案一:将监控逻辑整合到主脚本(推荐)

无需单独的监控脚本,直接在主脚本中启动program 1后,并行执行监控逻辑:

import subprocess
import time

# 启动program 1,获取进程对象
proc_program1 = subprocess.Popen(
    cmd,
    cwd=current_working_directory,
    shell=True,
    stdout=subprocess.DEVNULL,
    stderr=subprocess.STDOUT
)

# 配置监控参数
LOG_FILE = "/path/to/your/output.log"
# 替换为program 1完成时会输出到日志的特定标识,比如"Task finished successfully"
COMPLETION_MARKER = "任务完成标识"

# 循环监控
while proc_program1.poll() is None:  # 检查program 1是否仍在运行
    try:
        with open(LOG_FILE, "r") as f:
            if COMPLETION_MARKER in f.read():
                # 终止program 1,先尝试温和终止,不行则强制杀死
                proc_program1.terminate()
                # 如果terminate无效,改用kill:proc_program1.kill()
                print("检测到program 1完成,已终止进程")
                break
    except Exception as e:
        print(f"读取日志文件出错: {str(e)}")
    time.sleep(60)  # 每60秒检查一次

# 等待进程彻底结束,释放资源
proc_program1.wait()

方案二:使用独立监控脚本(需传递PID)

如果必须保留独立的监控脚本,需要将program 1的PID传递给它,让监控脚本能定位并终止目标进程:

主脚本代码

import subprocess

# 启动program 1
proc_program1 = subprocess.Popen(
    cmd,
    cwd=current_working_directory,
    shell=True,
    stdout=subprocess.DEVNULL,
    stderr=subprocess.STDOUT
)

# 启动监控脚本,传入program 1的PID和日志路径
monitor_script = "/home/.../Documents/pythonScriptFolder/monitor.py"
monitor_cmd = [
    "python3", monitor_script,
    str(proc_program1.pid), "/path/to/your/output.log"
]

subprocess.Popen(
    monitor_cmd,
    stdout=subprocess.DEVNULL,
    stderr=subprocess.STDOUT
)

# 等待program 1结束
proc_program1.wait()

监控脚本(monitor.py)代码

import os
import sys
import time

def main():
    if len(sys.argv) != 3:
        print("用法: python monitor.py <program1_pid> <log_file_path>")
        sys.exit(1)
    
    program1_pid = int(sys.argv[1])
    log_file = sys.argv[2]
    COMPLETION_MARKER = "任务完成标识"  # 替换为实际的完成标识

    while True:
        # 先检查program 1是否还存活
        try:
            os.kill(program1_pid, 0)  # 发送0信号仅用于检测进程是否存在
        except OSError:
            print("program 1已终止,监控结束")
            break
        
        # 读取日志检测完成状态
        try:
            with open(log_file, "r") as f:
                if COMPLETION_MARKER in f.read():
                    os.kill(program1_pid, 15)  # SIGTERM终止进程
                    # 无效则改用SIGKILL:os.kill(program1_pid, 9)
                    print("检测到完成,已终止program 1")
                    break
        except Exception as e:
            print(f"读取日志出错: {str(e)}")
        
        time.sleep(60)

if __name__ == "__main__":
    main()

内容的提问来源于stack exchange,提问作者Nicolas B

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 01:17:48