如何使用Python子进程终止进程组
我尝试使用Python子流程执行以下等效操作:如何使用Python子进程终止进程组,python,subprocess,kill,child-process,festival,Python,Subprocess,Kill,Child Process,Festival,我尝试使用Python子流程执行以下等效操作: >cat /var/log/dmesg | festival --tts & [1] 30875 >kill -9 -30875 请注意,我正在终止进程组(如进程ID号前面的负号所示),以便终止所有子进程 在Python中,我目前有以下代码,其中两个进程是通过管道创建和链接的 process_cat = subprocess.Popen([ "cat", "/var/log/dmesg" ], stdout =
>cat /var/log/dmesg | festival --tts &
[1] 30875
>kill -9 -30875
请注意,我正在终止进程组(如进程ID号前面的负号所示),以便终止所有子进程
在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)
有没有一种更优雅的方法可以做到这一点,也许只使用一个过程?您可以简化这一点,因为您很少需要
cat
。例如:
process_Festival = subprocess.Popen(["festival", "--tts", "/var/log/dmesg"])
后来
process_Festival.send_signal(1)
如果你用SIGHUP而不是siggill这样的信号来扼杀节日
将正确清理所有子流程
有一个非常好的关于python子流程的解释。将选项
preexec\u fn=os.setsid
添加到Popen:
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,您还可以在
Popen
调用中使用start\u new\u session=True
,而不是preexec\u fn
为什么它不够?也许可以看看os.setprgid
它是不够的,因为它不会杀死Festival的子进程。为了清楚起见,我将编辑这个问题。您好。谢谢你的简化建议。在这种情况下,您是完全正确的(尽管我想将管道用于其他更复杂的目的)。关于您的send_signal(9)
方法,问题是这相当于kill-9 30875
而不是kill-9-30875
。您的方法不会杀死Festival创建的许多子进程,这正是我所需要的。有一个os。killpg(pg,signal)
和process\u Festival.pid是进程id。不要使用kill-9,而是-1,这样Festival可以清理它的子进程。非常感谢您的建议。我需要杀死进程组,而不是让Festival终止子进程,因为子进程可以在终止之前继续运行很长时间,这不适合我的目的。您知道如何在子流程中使用os.killpg
函数吗?它似乎不能与单个子流程返回的PID一起使用。我找到了一篇关于会话和流程组之间差异的好文章。因此,如果要生成守护进程,需要使用os.setsid
或start\u new\u session
参数。但是,如果您正在生成子进程,而这些子进程在您从终端注销时应该会死亡,则更愿意使用preexec\u fn=os.setpgrp