python multiprocessing.Process.terminate - 如何杀死子进程

时间:2017-01-30 14:31:54

标签: python python-multithreading python-multiprocessing

此代码:

import multiprocessing as mp
from threading import Thread
import subprocess
import time

class WorkerProcess(mp.Process):
  def run(self):
      # Simulate long running task
      self.subprocess = subprocess.Popen(['python', '-c', 'import time; time.sleep(1000)'])
      self.code = self.subprocess.wait()


class ControlThread(Thread):
  def run():
      jobs = []
      for _ in range(2):
          job = WorkerProcess()
          jobs.append(job)
          job.start()

      # wait for a while and then kill jobs
      time.sleep(2)
      for job in jobs:
          job.terminate()

if __name__ == "__main__":
    controller = ControlThread()
    controller.start()

当我终止衍生的WorkerProcess实例时。他们死得很好,但子进程python -c 'import time; time.sleep(1000)一直运行直到完成。这是well documented in the official docs,但是如何杀死已杀死进程的子进程?

可能的灵魂可能是:

  • 在try / except块中捕获WorkerProcess.run()方法捕获SIGTERM,并终止subprocess.call call。但我不确定如何在WorkerProcess

  • 中捕获SIGTERM
  • 我也尝试在WorkerProcess中设置signal.signal(signal.SIGINT, handler),但我得到了ValuError,因为它只允许在主线程中设置。

我现在该怎么办?

2 个答案:

答案 0 :(得分:2)

编辑:正如@svalorzen在评论中指出的那样,由于self.subprocess的引用丢失,因此无法正常工作。

最后得到了一个干净,可接受的解决方案。由于mp.Process.terminate是一个方法,我们可以覆盖它。

class WorkerProcess(mp.Process):
    def run(self):
        # Simulate long running task
        self.subprocess = subprocess.Popen(['python', '-c', 'import time; time.sleep(1000)'])
        self.code = self.subprocess.wait()

    # HERE
    def terminate(self):
      self.subprocess.terminate()
      super(WorkerProcess, self).terminate()

答案 1 :(得分:0)

您可以使用队列向您的子流程发送消息,并在退出之前让他们很好地终止他们的孩子。除了主线程之外,您无法在其他任何地方使用信号,因此信号不适用于此。

奇怪的是,当我修改这样的代码时,即使我用control + C中断它,子进程也会死掉。不过,这可能与操作系统有关。

import multiprocessing as mp
from threading import Thread
import subprocess
import time
from Queue import Empty


class WorkerProcess(mp.Process):
    def __init__(self,que):
        super(WorkerProcess,self).__init__()
        self.queue = que

    def run(self):
        # Simulate long running task
        self.subprocess = subprocess.Popen(['python', '-c', 'import time; time.sleep(1000)'])
        while True:
            a = self.subprocess.poll()
            if a is None:
                time.sleep(1)
                try:
                    if self.queue.get(0) == "exit":
                        print "kill"
                        self.subprocess.kill()
                        self.subprocess.wait()
                        break
                    else:
                        pass
                except Empty:
                    pass
                print "run"
            else:
                print "exiting"


class ControlThread(Thread):

    def run(self):
        jobs = []
        queues = []
        for _ in range(2):
            q = mp.Queue()
            job = WorkerProcess(q)
            queues.append(q)
            jobs.append(job)
            job.start()

        # wait for a while and then kill jobs
        time.sleep(5)
        for q in queues:
            q.put("exit")
        time.sleep(30)

if __name__ == "__main__":
    controller = ControlThread()
    controller.start()

希望这会有所帮助。

哈努哈利