2017-01-30 83 views
2

此代码:蟒蛇multiprocessing.Process.terminate - 如何杀死子进程

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,但我该如何杀死死亡进程的子进程?

甲possbile soultion可能是:

  • 裹WorkerProcess.run()内的try /方法除了块捕捉SIGTERM,并终止subprocess.call call。但我不知道如何捕捉工人进程中的SIGTERM

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

现在我该怎么办?

回答

2

终于来到了一个干净的,可以接受的解决方案。由于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() 
0

您可以使用队列来邮件到您的子流程,并要求他们退出精美自己之前终止自己的孩子。除了主线程外,你不能在其他任何地方使用信号,所以信号不适合这个。

奇怪的是,当我修改代码这样,即使我与对照+ 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() 

希望这会有所帮助。

Hannu

+0

嗨,对不起,谢谢你的回答,但我想避免使用队列。根据正确结束的例子,你是对的。这仅仅是一个虚拟的例子,用来说明工作流程,它(idk为什么)有效(不明智的选择,我同意)。在我的真实情况下,这个过程只是继续运行 –