以下是python多处理中daemon
标志的官方解释:
当进程退出时,它会尝试终止所有守护进程子进程。
根据我的理解,父进程将终止其守护进程标志在退出时设置为True的子进程。
以下是我用来证明猜测的代码。但结果却不同。
import multiprocessing
def child():
while True:
pass
for x in xrange(1, 4):
proc = multiprocessing.Process(target=child, args=())
proc.daemon=True
proc.start()
while True:
pass
以上启动了4个子进程和一个主进程。 我杀死了主要进程,但是4个孩子没有退出。
那么为什么它们没有被main终止,因为守护进程设置为true?
答案 0 :(得分:2)
备注强>:
xrange(1, 4)
将产生3个值而不是4个(因此,只有3个孩子)事情并非如此。文档([Python 2]: daemon)应该更具体。
事情是多处理注册清理功能以在退出时杀死所有 deamonic 子项。这是通过[Python 2]: atexit - Exit handlers:
完成的注意:当程序被Python未处理的信号杀死,检测到Python致命内部错误或os._exit()时,不会调用通过此模块注册的函数被称为。
您无法处理 TERM 信号(默认情况下由 kill 命令发送),因此主进程不会调用清理功能(离开它的孩子们跑步。)
我修改了你的代码以更好地说明行为。
code.py :
#!/usr/bin/env python2
import multiprocessing
import os
import time
print_text = "Output from process {:s} - pid: {:d}, ppid: {:d}"
def child(name):
while True:
print(print_text.format(name, os.getpid(), os.getppid()))
time.sleep(1)
if __name__ == "__main__":
procs = list()
for x in xrange(1, 3):
proc_name = "Child{:d}".format(x)
proc = multiprocessing.Process(target=child, args=(proc_name,))
proc.daemon = True #x % 2 == 0
print("Process {:s} daemon: {:}".format(proc_name, proc.daemon))
procs.append(proc)
for proc in procs:
proc.start()
counter = 0
while counter < 3:
print(print_text.format("Main", os.getpid(), os.getppid()))
time.sleep(1)
counter += 1
备注强>:
time.sleep
次调用(1秒),以避免产生输出太多if __name__ == "__main__":
中附上所有内容,以便在导入模块proc.daemon
,然后监控输出和ps -ef | grep "code.py"
输出<强>输出强>:
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049604997]> python code.py Process Child1 daemon: True Process Child2 daemon: True Output from process Main - pid: 20593, ppid: 12794 Output from process Child2 - pid: 20595, ppid: 20593 Output from process Child1 - pid: 20594, ppid: 20593 Output from process Main - pid: 20593, ppid: 12794 Output from process Child2 - pid: 20595, ppid: 20593 Output from process Child1 - pid: 20594, ppid: 20593 Output from process Main - pid: 20593, ppid: 12794 Output from process Child2 - pid: 20595, ppid: 20593 Output from process Child1 - pid: 20594, ppid: 20593
答案 1 :(得分:0)
是的,您的理解是正确的,您测试此代码的代码也有效。
我刚刚添加了一些睡眠语句来调试输出(没有sleep
,很难从巨大的打印输出中推断出来):
import multiprocessing
import time
import sys
print("main")
def child():
while True:
print("child")
time.sleep(3)
for x in xrange(1, 4):
proc = multiprocessing.Process(target=child, args=())
proc.daemon=True
proc.start()
time.sleep(7)
print("exit")
sys.exit() # this exits the main process
现在,当我运行这个脚本时,当它运行时,我做了一个ps aux
,可以看到从这个脚本运行的四个进程。 7秒后,当我再次ps aux
时,我再也看不到这些进程在运行 - 这意味着:
当主进程退出时,它终止了所有守护进程的子进程。
之后,我还将proc.daemon
设置为False
,然后再次运行该脚本。这一次,即使在7秒之后,当我执行ps aux
时,我仍然可以看到子进程正在运行(因为它们现在是非守护进程,即使在主进程终止后它们也不会退出)。
所以这可以按预期工作 - 请告诉我你是否还有问题。
编辑1:
感谢@CristiFati指出原始的清理问题。
此代码有效,因为调用sys.exit()
也会将atexit
回调注册为详细here。