如何使用subprocess停止由单个脚本产生的所有subprocess

我需要在我的包的一部分上运行一个unit testing,对我来说最好的办法是控制启动它,然后杀死multiprocessing模块产生的所有进程。

以下是我正在谈论的内容:

test.py

 import logging import multiprocessing import time import random log = logging.getLogger(__name__) def start_consumers(conf, worker_count=5): manager = WorkerManager(conf, worker_count) manager.start() class WorkerManager(): def __init__(self, conf, worker_count=5): self.workers = [] for num in range(worker_count): self.workers.append(WorkHandler(conf)) def start(self): for worker in self.workers: worker.daemon = True worker.start() print 'started' for worker in self.workers: worker.join() class WorkHandler(multiprocessing.Process): def __init__(self, conf, *args, **kwargs): super(WorkHandler, self).__init__(*args, **kwargs) self.conf = conf self.name = str(random.randint(0,100)) def run(self): while True: print self.conf['foo'], self.name time.sleep(3) if __name__ == "__main__": conf = {'foo': 'bar'} start_consumers(conf) 

现在,如果我从linuxterminal运行这个testing,我可以看到打印语句,如果我这样做: ps aux | grep python ps aux | grep python我看到所有产生的subprocess

 sergey 4081 0.0 0.1 71684 13164 pts/3 S+ 08:58 0:00 python sergey 4108 0.3 0.0 39092 6472 pts/3 S+ 08:59 0:00 python test.py sergey 4109 0.0 0.0 39092 4576 pts/3 S+ 08:59 0:00 python test.py sergey 4110 0.0 0.0 39092 4568 pts/3 S+ 08:59 0:00 python test.py sergey 4111 0.0 0.0 39092 4576 pts/3 S+ 08:59 0:00 python test.py sergey 4112 0.0 0.0 39092 4584 pts/3 S+ 08:59 0:00 python test.py sergey 4113 0.0 0.0 39092 4580 pts/3 S+ 08:59 0:00 python test.py sergey 4115 0.0 0.0 13588 944 pts/7 S+ 08:59 0:00 grep --color=auto python 

现在,如果我试图运行与subprocess test.py相同的test.py一切工作正常,直到我需要杀死他们:

 >>> import subprocess as s >>> p = s.Popen(['python', 'test.py'], stdout=s.PIPE) 

问题:

当我在terminal中按Ctrl+C时,为了达到类似的行为,用这个variablesp做什么最优雅的方法是什么?
换句话说,我想实现类似于pkill -f "test.py"

更新:

p.kill()p.terminate()不会做我所需要的:

这是我做了他们之后的结果:

 sergey 4438 0.0 0.0 0 0 pts/3 Z+ 09:16 0:00 [python] <defunct> sergey 4439 0.0 0.0 39092 4572 pts/3 S+ 09:16 0:00 python test.py sergey 4440 0.0 0.0 39092 4568 pts/3 S+ 09:16 0:00 python test.py sergey 4441 0.0 0.0 39092 4576 pts/3 S+ 09:16 0:00 python test.py sergey 4442 0.0 0.0 39092 4580 pts/3 S+ 09:16 0:00 python test.py sergey 4443 0.0 0.0 39092 4580 pts/3 S+ 09:16 0:00 python test.py 

我相信你要找的是subprocess对象的subprocess.terminate()subprocess.kill()方法。

您可能必须将其与使用atexit注册的方法相结合,该方法遍历子进程列表并终止它们。 EX:

 def terminate_children(children): for process in children: process.terminate() ... # Somewhere else in your code children = [s.Popen(['python', 'test.py'], stdout=s.PIPE) for i in range(number_processes)] # Spools up number_processes child processes atexit.register(terminate_children, children) # where children is a list of subprocesses 

这会优雅地终止父进程时正常终止所有子进程。

如果您试图从完全独立的脚本中终止进程而不直接引用子代码,请参见此处 。 你基本上会想看看python os 进程管理方法

你可以尝试创建一个新的会话,并使用os.killpg()os.killpg()所有后代进程:

 import os import signal from subprocess import Popen p = Popen('python test.py', shell=True, preexec_fn=os.setsid) # ... later os.killpg(p.pid, signal.SIGTERM) # send signal to the process group 

请参阅如何终止使用shell = True启动的python子进程 。