正确终止使用subprocess.popen启动的进程及其子进程的方法(适用于Windows和Linux)

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) 在某些情况下可以工作,但正确的方法是什么?终端又是如何做到的?


1
你尝试过在这个帖子中建议的使用组进程吗? https://dev59.com/pW445IYBdhLWcg3wl7TW - Henri Korhonen
1个回答

0

正如Henri Korhonen在评论中提到的,分组进程应该有所帮助。此外,如果您使用的是Cygwin Python并且启动Windows应用程序,则似乎Cygwin Python无法杀死子进程。对于这些情况,您需要运行TASKKILL。TASKKILL还接受一个组参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接