使用python-daemon时,我正在创建子流程,如:
import multiprocessing
class Worker(multiprocessing.Process):
def __init__(self, queue):
self.queue = queue # we wait for things from this in Worker.run()
...
q = multiprocessing.Queue()
with daemon.DaemonContext():
for i in xrange(3):
Worker(q)
while True: # let the Workers do their thing
q.put(_something_we_wait_for())
当我使用Ctrl-C或SIGTERM等杀死父守护进程(即不是工作进程)时,子进程不会死亡。怎么杀孩子?
我的第一个想法是用atexit杀死所有的工人,比如:
with daemon.DaemonContext():
workers = list()
for i in xrange(3):
workers.append(Worker(q))
@atexit.register
def kill_the_children():
for w in workers:
w.terminate()
while True: # let the Workers do their thing
q.put(_something_we_wait_for())
然而,守护进程的子进程是很难处理的事情,我不得不思考和输入应该如何做。
谢谢你。
Atexit不会成功——它只在成功的非信号终止时运行——请参阅docs顶部附近的注释。您需要通过两种方法之一设置信号处理。
听起来更简单的选项:在工作进程上设置守护进程标志,每http://docs.python.org/library/multiprocessing.html#process-and-exceptions
听起来有些困难的选项:PEP-3143似乎意味着python守护进程中有一种内置的方法来钩住程序清理需求。
你的选择有点有限。如果在
Worker
类的构造函数中执行self.daemon = True
操作无法解决问题,并且尝试捕获父类中的信号(即SIGTERM, SIGINT
)也无法工作,则可能必须尝试相反的解决方案-而不是让父类杀死子类,而是让子类在父类死亡时自杀。第一步是将构造函数赋给父进程的
Worker
的PID
(可以使用os.getpid()
来实现)。然后,不要只是在工作循环中执行self.queue.get()
,而是执行如下操作:上面的解决方案检查父PID是否与它原来的不同(即,如果子进程被
init
或lauchd
采用是因为父进程已死亡)-请参见reference。但是,如果由于某种原因这不起作用,您可以用以下函数替换它(改编自here):现在,当父母去世时(不管是什么原因),孩子们会像苍蝇一样自发地掉下来-就像你想要的,你这个恶魔!
:-D
当第一次创建子进程时(比如在
self.myppid
)和self.myppid
与getppid()
不同时,不能只存储父进程的pid,这意味着父进程已经死亡。您还可以使用信号来避免继续检查父项是否已更改。我不知道python的具体细节,但是像here (at the bottom of the page)这样的描述可能会起作用。
相关问题 更多 >
编程相关推荐