我想创建一个父进程,它将创建许多子进程.由于父进程负责创建子进程,因此父进程不关心子进程的状态.
由于subprocess.call是阻塞的,它不起作用.因此我使用subprocess.Popen来替换call.然而,一旦孩子终止(链接),Popen将生成僵尸(已解散)进程.
有没有办法解决这个问题?
提前致谢
tor*_*rek 15
有很多方法可以解决这个问题.关键点在于存在僵尸/"失效"进程,以便父进程可以收集其状态.
作为流程的创建者,您可以宣布忽略状态的意图.POSIX方法是设置标志SA_NOCLDWAIT(使用sigaction).这在Python中有点痛苦; 但大多数类Unix系统允许你简单地忽略SIGCHLD/ SIGCLD(拼写从一个类Unix系统到另一个系统不同),这在Python中很容易做到:
import signal
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
或者,如果由于某种原因这不可用或者在您的系统上不起作用,您可以使用旧的备用技巧:不要只分叉一次,分叉两次.在第一个孩子,叉第二个孩子; 在第二个孩子中,使用execve(或类似)运行所需的程序; 然后在第一个孩子,退出(带_exit).在原始父级中,使用wait或者waidpid操作系统提供的任何内容,并收集第一个孩子的状态.
这样做的原因是第二个孩子现在变成了一个"孤儿"(它的父母,第一个孩子,死了,并且是由你的原始过程收集的).作为孤儿,它被移交给代理父母(具体地说,"init"),它始终是 - wait并因此立即收集所有的僵尸.
除了双分支之外,您还可以将子流程置于各自的单独会话中和/或放弃控制终端访问("daemonize",以Unix-y术语表示).(这有点乱,并且依赖于操作系统;我之前编写过它,但对于一些我现在无法访问的公司代码.)
最后,您可以定期收集这些流程.如果您正在使用该subprocess模块,只需.poll在方便的时候调用每个进程上的函数.None如果进程仍在运行,则返回,如果已完成,则退出状态(已收集).如果有些仍然在运行,那么你的主程序可以在它们继续运行的同时退出; 在那时,他们变成了孤儿,就像上面的方法#2一样.
"忽略SIGCHLD"方法简单易行,但缺点是干扰创建和等待子进程的库例程.Python 2.7及更高版本(http://bugs.python.org/issue15756)中有一个解决方法,但这意味着库例程无法在这些子流程中看到任何失败.
[编辑:http://bugs.python.org/issue1731717用于p.wait(),p进程来自哪里subprocess.Popen; 15756专门用于p.poll(); 但无论如何,如果你没有修复,你必须求助于方法2,3或4.]