此代码:
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
我也尝试在WorkerProcess中设置signal.signal(signal.SIGINT, handler)
,但我得到了ValuError,因为它只允许在主线程中设置。
我现在该怎么办?
答案 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()
希望这会有所帮助。
哈努哈利