如何使用Python子进程终止进程组

时间:2015-08-26 09:21:35

标签: python subprocess kill child-process festival

我正在尝试使用Python子进程执行以下操作:

>cat /var/log/dmesg | festival --tts &
[1] 30875
>kill -9 -30875

请注意,我正在查看进程(由前面加上进程ID编号的负号表示),以便终止所有子进程的Festival启动。

在Python中,我目前有以下代码,其中创建了两个进程并通过管道进行链接。

process_cat = subprocess.Popen([
    "cat",
    "/var/log/dmesg"
], stdout = subprocess.PIPE)
process_Festival = subprocess.Popen([
    "festival",
    "--tts"
], stdin = process_cat.stdout, stdout = subprocess.PIPE)

我应该如何以与上面显示的Bash方式相同的方式杀死这些进程及其子进程?以下方法是不够的,因为它不会杀死子进程:

os.kill(process_cat.pid, signal.SIGKILL)
os.kill(process_Festival.pid, signal.SIGKILL)

有没有更优雅的方法来做到这一点,也许只使用一个流程?

1 个答案:

答案 0 :(得分:14)

您可以轻松简化这一点,因为您很少需要cat |。例如:

process_Festival = subprocess.Popen(["festival", "--tts", "/var/log/dmesg"])

然后再

process_Festival.send_signal(1)

如果你用像SIGHUP这样的信号杀死节日而不是SIGKILL它 将正确清理所有子流程。

使用python子进程对how to create a new process group有一个非常好的解释。向Popen添加选项preexec_fn=os.setsid

process_Festival = subprocess.Popen(["festival", "--tts", "/var/log/dmesg"],preexec_fn=os.setsid)

然后,您可以从流程ID中获取流程组并发出信号:

pgrp = os.getpgid(process_Festival.pid)
os.killpg(pgrp, signal.SIGINT)

注意:由于Python 3.2 ,您还可以在start_new_session=True调用中使用Popen而不是preexec_fn