我需要在我的包的一部分上运行一个unit testing,对我来说最好的办法是控制启动它,然后杀死multiprocessing
模块产生的所有进程。
以下是我正在谈论的内容:
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子进程 。