发布于2026-07-12 阅读(0)
扫一扫,手机访问
本文介绍一种简洁稳健的方案,使用 subprocess 直接管理两个外部可执行文件的生命周期,并通过 multiprocessing.Event 实现进程间协调,避免序列化错误与资源竞争,确保 process1.exe 在 process2.exe 退出时被及时终止。
先说说这类问题的核心思路。在Python脚本里同时控制两个外部exe进程,比如process1.exe和process2.exe,最头疼的地方在于:进程的生命周期必须强耦合在一起。换言之,process2.exe一旦异常退出,process1.exe必须立刻跟着终止,所有后续的检查逻辑也得同步停掉,不能拖泥带水。
原方案试图用multiprocessing.Process封装psutil的进程探测逻辑,看起来挺巧妙,但实际操作中却踩了坑——传递不可序列化的对象(比如psutil.Process实例、weakref等)直接引发了TypeError: cannot pickle 'weakref.ReferenceType' object。这个错误在Windows上特别常见,因为spawn启动方式对跨进程对象序列化有硬性限制,简单说就是:子进程拿不到主进程里那些复杂的东西。
那怎么破?根本解法其实就一句话:别在子进程里传复杂对象,改用更轻量、更可控的协作模型。
核心思想很直接:主进程亲自启动并持有两个subprocess.Popen实例,用process2.wait()阻塞等待它结束(这个调用天然支持异常退出,无论是正常关闭还是崩溃),然后主动干掉process1。同时,把耗时的检查逻辑(比如checkStatus)放到独立子进程里,用Event通知它提前退出。这样一来,所有操作都在主进程的掌控之中,既避免了序列化错误,也杜绝了竞态条件。
优化后的代码长这样:
import subprocess
import multiprocessing
import time
def checkStatus(event, queue):
# 示例:模拟耗时检查逻辑(如轮询日志、验证端口、读取共享内存等)
for i in range(10):
if event.is_set(): # 主进程已发出终止信号
print("checkStatus: 接收到终止信号,提前退出")
break
print(f"checkStatus: 执行第 {i+1} 次检查...")
time.sleep(1)
else:
print("checkStatus: 检查完成")
queue.put("checkStatus Completed!")
# 注意:此处不再调用 event.wait(),避免死锁 —— 终止信号由主进程单向发出
def main():
# 启动两个进程(注意路径和权限)
process1 = subprocess.Popen(["./process1.exe"])
process2 = subprocess.Popen(
["./process2.exe"],
creationflags=subprocess.CREATE_NEW_CONSOLE
)
# 创建通信机制
queue = multiprocessing.Queue()
event = multiprocessing.Event()
# 启动检查子进程
p_check = multiprocessing.Process(target=checkStatus, args=(event, queue))
p_check.start()
try:
# 关键:阻塞等待 process2 结束(无论正常退出或崩溃)
process2.wait()
print("process2.exe 已退出,准备终止 process1.exe...")
# 立即终止 process1
process1.terminate()
try:
process1.wait(timeout=5) # 等待优雅退出
except subprocess.TimeoutExpired:
process1.kill() # 强制终止
print("process1.exe 未响应,已强制杀死")
# 通知检查进程终止
event.set()
# 等待检查进程结束
p_check.join(timeout=2)
if p_check.is_alive():
p_check.terminate()
p_check.join()
finally:
# 清理队列输出
while not queue.empty():
print(queue.get_nowait())
if __name__ == "__main__":
main()
整体来看,这个方案用最小依赖、最简逻辑实现了目标:process2的生命周期完全主导整个流程,主进程充当协调中枢,子进程只承担单一职责,彻底规避了序列化陷阱与竞态条件。 既干净又务实,值得在实际项目中直接落地。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8