如何停止使用子进程的单个脚本生成的所有子进程

2024-06-16 08:25:57 发布

您现在位置:Python中文网/ 问答频道 /正文

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

我说的是:

在测试.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)

现在,如果我从linux终端运行这个测试,我可以看到打印语句,如果我这样做的话: ps aux | grep python我看到所有生成的子进程:

^{pr2}$

现在,如果我试图用test.py运行相同的test.py在我需要杀死它们之前,一切都会正常工作:

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

问题是:

当我在终端中按Ctrl+C时,用这个变量p来实现类似的行为,最优雅的方法是什么?
换句话说,我想得到一个类似pkill -f "test.py"的结果

更新:

p.kill()或{}无法满足我的需要:

以下是我吃了它们之后的结果:

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

Tags: namepytestimportselfinitconfdef
2条回答

我相信您要寻找的是subprocess.terminate()和{}方法。在

您可能需要将其与注册到atexit的方法结合起来,该方法会在子进程列表中迭代并终止它们。例如:

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

当您优雅地终止父进程时,这将优雅地终止所有子进程。在

如果您试图从一个完全独立的脚本中终止进程,而不直接引用子代码,请参见here。您基本上想看看python osprocess management methods

您可以尝试使用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

How to terminate a python subprocess launched with shell=True。在

相关问题 更多 >