3

我正在努力处理我从 Popen 开始的一些进程,这些进程启动了子进程。当我在终端中手动启动这些进程时,如果我发送 CTRL+C,每个进程都会按预期终止。但是使用 subprocess.Popen 在 python 程序中运行任何终止进程的尝试只会摆脱父进程而不是其子进程。

我尝试了 .terminate() ..kill() 以及 ..send_signal() 与 signal.SIGBREAK、signal.SIGTERM,但在每种情况下我都只是终止父进程。

通过这个父进程,我可以重现错误行为:

#!/usr/bin/python

import time
import sys
import os
import subprocess
import signal

if __name__ == "__main__":
  print os.getpid(), "MAIN: start a process.."
  p = subprocess.Popen([sys.executable, 'process_to_shutdown.py'])
  print os.getpid(), "MAIN: started process", p.pid
  time.sleep(2)
  print os.getpid(), "MAIN: kill the process"
  # these just terminate the parent:
  #p.terminate()
  #p.kill()
  #os.kill(p.pid, signal.SIGINT) 
  #os.kill(p.pid, signal.SIGTERM)
  os.kill(p.pid, signal.SIGABRT)
  p.wait()
  print os.getpid(), "MAIN: job done - ciao"

现实生活中的子进程是来自 Django 的 manage.py,它产生一些子进程并等待 CRTL-C。但下面的例子似乎也有效:

#!/usr/bin/python

import time
import sys
import os
import subprocess

if __name__ == "__main__":

    timeout = int(sys.argv[1]) if len(sys.argv) >= 2 else 0

    if timeout == 0:
        p = subprocess.Popen([sys.executable, '-u', __file__, '13'])
        print os.getpid(), "just waiting..."
        p.wait()

    else:
        for i in range(timeout):
            time.sleep(1)
            print os.getpid(), i, "alive!"
            sys.stdout.flush()

    print os.getpid(), "ciao"

所以我的问题很简单:我如何杀死第一个示例中的进程并摆脱子进程?在 Windows 上 os.kill(p.pid, signal.CTRL_C_EVENT) 在某些情况下似乎可以工作,但是正确的方法是什么?终端是如何做到的?

4

1 回答 1

0

就像 Henri Korhonen 在评论中提到的那样,分组流程应该会有所帮助。此外,如果您在 Windows 上并且这是启动 Windows 应用程序的 Cygwin Python,那么 Cygwin Python 似乎无法杀死孩子。对于这些情况,您需要运行 TASKKILL。TASKKILL 也接受一个组参数。

于 2014-03-14T16:30:56.887 回答