在Python中,只要任何非守护子进程都在运行,父进程是否继续存在

时间:2019-01-31 09:48:01

标签: python python-multiprocessing

我正在使用Python的多处理模块。我正在测试以下代码:

from multiprocessing import *
from time import sleep

def f():
    print ('in child#1 proc')
    sleep(2)
    print('ch#1 ends')

def f1() :
    print ('in child#2 proc')
    sleep(10)
    print('ch#2 ends')


if __name__ == '__main__':
    p = Process(target=f)
    p1 = Process(target=f1, daemon=True)
    p.start()
    p1.start()
    sleep(1)

    print ('child procs started')

我有以下发现:

  • 第一个子进程p运行2秒
  • 1秒钟后,第二个子进程p1变成僵尸
  • 父(主)进程一直运行(处于活动状态),直到子#1(非守护进程)正在运行,即2秒钟

现在我有以下查询:

  • 为什么父(主)流程完成执行后仍处于活动状态?请注意,父级不会对join执行p
  • 为什么守护程序子项p1在1秒后会变成僵尸?请注意,父(主)进程实际上一直处于活动状态,直到运行p为止。

我已经在ubuntu上执行了上述程序。 我的观察基于ubuntu上ps命令的输出

2 个答案:

答案 0 :(得分:1)

总结并继续讨论其他答案的评论:

  

为什么父(主)进程完成后应该处于活动状态   执行?请注意,父级不会对join执行p

multiprocessing试图确保使用它的程序运行良好。也就是说,它会尝试自行清除。为此,它利用了atexit模块,该模块可让您注册在解释器进程准备正常终止时要执行的出口处理程序。
multiprocessing定义并注册函数_exit_function,该函数首先在所有仍在运行的守护程序子级上调用terminate(),然后在所有其余非守护程序子级上调用join()。由于join()被阻止,因此父级会一直等待,直到非守护进程的子级终止为止。另一方面,terminate()不会被阻止,它只是向孩子发送SIGTERM信号(在Unix上)并返回。

这使我们想到:

  

为什么守护程序子项p1在1秒后会变成僵尸?注意   父(主)进程实际上一直处于活动状态,直到时间p   运行。

这是因为父级已经到达其指令的末尾,并且解释器准备终止,即它执行了注册的退出处理程序。守护子级p1接收到SIGTERM信号。由于SIGTERM被允许在进程内被捕获和处理,因此不命令该子项立即关闭,而是给其机会自己进行一些清理。这就是使p1显示为<defunct>的原因。内核知道已指示终止进程,但该进程尚未终止。
在给定的情况下,p1尚未有机会兑现SIGTERM信号,大概是因为它仍然执行sleep()。至少自Python 3.5起:

  

该函数现在至少睡眠 secs ,即使睡眠被中断   除非信号处理程序引发异常(有关原理,请参见PEP 475)。

答案 1 :(得分:0)

父级保持活动状态,因为它是应用程序的根目录。当孩子正在处理时,它将保留在内存中。注意,join等待子项退出,然后将控制权交还给父项。如果您不加入,父母将退出,但仍保留在内存中。

p1会僵尸,因为父母在睡眠1之后退出。p1与p一起保持生命,因为您不守护p。如果您不守护进程,而是调用它的start,则该控件将传递给子进程,当子进程完成时,它将把控件传递回父进程。如果您执行守护程序,它将控制父级并在后面运行子级。