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

线程中使用subprocess启动子进程后无法正常终止该如何解决?

问题根因

  • 无法终止子进程的核心原因是subprocess.Popen中使用了shell=True参数:Windows平台下该参数会创建一个中间cmd.exe外壳进程,你调用kill()/terminate()只能终止这个外壳进程,真正运行test.py的Python子进程会变成孤儿进程继续运行,所以看不到停止效果。
  • 额外问题:使用了低层级的_thread模块,没有进程退出后的清理逻辑,多次启动停止会留下无效进程句柄。

解决方案

方案1:直接去掉shell=True(无额外依赖,优先推荐)

把subprocess.Popen的shell=True参数删除,直接传递启动参数列表,此时Popen返回的进程句柄就是运行test.py的真实Python进程,直接调用kill()即可终止。
修改后的main.py代码如下:

import subprocess
import threading

processes = []

def add_process(file_name):
    # 去掉shell=True,直接拿到真实Python进程句柄
    p = subprocess.Popen(["python", file_name])
    processes.append(p)
    print("Waiting the process...")
    p.wait()
    # 进程退出后自动清理列表
    processes.remove(p)

while True:
    try:
        ui = input("> ")
        if ui == "start":
            # 用标准threading模块代替低层级的_thread
            threading.Thread(target=add_process, args=("test.py",), daemon=True).start()
            print("Process started.")
        elif ui == "stop":
            if len(processes) > 0:
                p = processes.pop()
                p.kill()
                print("Process killed.")
    except KeyboardInterrupt:
        # 主程序退出前清理所有剩余子进程
        for p in processes:
            p.kill()
        print("Exiting Program!")
        break

方案2:必须保留shell=True时的处理

如果你的场景必须使用shell=True(比如要调用shell内置命令),可以用Windows自带的taskkill命令终止整个进程树,替换原有的kill逻辑即可:

# 终止p对应的进程及其所有子进程
import os
os.system(f'taskkill /F /T /PID {p.pid}')

替代模块说明

如果需要更便捷的进程管理能力,可以使用psutil第三方库,它支持跨平台的进程查询、子进程遍历、批量终止等操作,比标准库subprocess的进程管理能力更灵活,适合复杂的进程控制场景。

内容的提问来源于stack exchange,提问作者Parvat R

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 14:15:01