开发者社区 问答 正文

[Windows,python]如何使由subprocee.Popen()启动的进程在父进程终止时自

在我的python脚本中,我使用以下命令开始了一些过程:


p1 = subprocess.Popen('p1.exe')
p2 = subprocess.Popen('p2.exe')

当这两个子进程启动时,当父进程死于某些错误时,它们将不会被杀死。 我希望这三个进程,父进程,p1和p2同时退出。那就是他们中的任何一个都终止了,使得其他所有都终止了。如何在Windows上进行管理?那Linux呢?

展开
收起
Puppet 2019-12-11 09:00:06 776 分享 版权
阿里云 AI 助理回答

在Python中,管理子进程与父进程之间的依赖关系,确保它们能够一起终止,可以通过几种方式实现。对于您的需求,在Windows和Linux上都可以采用相似的策略,但具体实现细节可能有所不同。

Windows 和 Linux 共通方案:信号处理和进程组

  1. 使用subprocess.Popenpreexec_fn参数(Linux)或creationflags参数(Windows)创建进程组

    • 在Linux上,你可以通过传递一个函数到preexec_fn参数来设置新的会话ID,这将创建一个新的进程组。
    import os
    import subprocess
    
    def setpgid():
       os.setpgrp()
    
    p1 = subprocess.Popen('p1.exe', preexec_fn=setpgid)
    p2 = subprocess.Popen('p2.exe', preexec_fn=setpgid)
    
    • 在Windows上,你不能直接设置进程组,但可以使用CREATE_NEW_PROCESS_GROUP标志来模拟类似行为(注意,这不会像Linux那样形成严格意义上的进程组,但在某些情况下可以帮助控制进程)。
    CREATE_NEW_PROCESS_GROUP = 0x00000200
    p1 = subprocess.Popen('p1.exe', creationflags=CREATE_NEW_PROCESS_GROUP)
    p2 = subprocess.Popen('p2.exe', creationflags=CREATE_NEW_PROCESS_GROUP)
    
  2. 监听父进程中的信号,并在接收到信号时终止所有子进程

    • 在Linux上,可以在父进程中安装信号处理器来捕获如SIGINT(Ctrl+C)等信号,并在这些信号被接收时终止子进程。
    import signal
    
    def sigint_handler(signum, frame):
       p1.terminate()
       p2.terminate()
       exit(0)
    
    signal.signal(signal.SIGINT, sigint_handler)
    
    • 在Windows上,虽然没有直接对应的信号机制,但可以通过异常处理或者自定义事件来模拟这一行为,例如使用try/except块来捕获特定的异常并终止子进程。

特定于操作系统的考虑:

  • Linux:上述方法较为直接,因为Linux系统支持精细的信号处理和进程组管理。

  • Windows:由于Windows不完全支持POSIX标准的信号处理,因此处理起来稍微复杂一些。一种替代方案是使用线程或定时器检查父进程状态,并在需要时调用terminate()方法结束子进程。另外,也可以考虑使用第三方库如psutil来更方便地管理和监控进程。

综合示例(简化版,未涵盖所有细节):

import os
import sys
import subprocess
import signal

def terminate_children_and_exit():
    for child in children:
        child.terminate()
    sys.exit(0)

# 对于Linux
if sys.platform == 'linux':
    def setpgid():
        os.setpgrp()
    children = [subprocess.Popen(['p1.exe'], preexec_fn=setpgid),
                subprocess.Popen(['p2.exe'], preexec_fn=setpgid)]
    signal.signal(signal.SIGINT, lambda signum, frame: terminate_children_and_exit())

# 对于Windows
elif sys.platform == 'win32':
    CREATE_NEW_PROCESS_GROUP = 0x00000200
    children = [subprocess.Popen(['p1.exe'], creationflags=CREATE_NEW_PROCESS_GROUP),
                subprocess.Popen(['p2.exe'], creationflags=CREATE_NEW_PROCESS_GROUP)]
    # Windows下信号处理较复杂,这里简化处理,实际应用中可能需要更复杂的逻辑来响应退出请求

# 监听其他情况或添加通用逻辑
else:
    print("Unsupported platform.")
    sys.exit(1)

# 父进程等待子进程结束,或根据需要添加其他逻辑
for child in children:
    child.wait()

请注意,以上代码是一个简化的示例,实际应用中可能需要根据具体需求调整。特别是在Windows环境下,可能需要额外的逻辑来模拟信号处理的行为。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答