8

我正在尝试使用 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)

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

4

1 回答 1

20

您可以简化很多,因为您很少需要cat |。例如:

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

然后稍后

process_Festival.send_signal(1)

如果您使用 SIGHUP 而不是 SIGKILL 之类的信号来终止节日,它将正确清理所有子进程。


关于如何使用 python 子进程创建新进程组有一个很好的解释。向 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=TruePopen调用中使用preexec_fn.

于 2015-08-26T09:35:13.910 回答