为什么没有join()守护程序不退出
Why doesn't the daemon program exit without join()
下面的 link 答案可能就在我眼前,但我还是不明白。我确定在有人向我解释之后,达尔文会给我打电话。
示例是 at this link here,尽管我做了一些更改以尝试进行实验并帮助我理解。
代码如下:
import multiprocessing
import time
import sys
def daemon():
p = multiprocessing.current_process()
print 'Starting: ', p.name, p.pid
sys.stdout.flush()
time.sleep(2)
print 'Exiting: ', p.name, p.pid
sys.stdout.flush()
def non_daemon():
p = multiprocessing.current_process()
print 'Starting: ', p.name, p.pid
sys.stdout.flush()
time.sleep(6)
print 'Exiting: ', p.name, p.pid
sys.stdout.flush()
if __name__ == '__main__':
d = multiprocessing.Process(name='daemon', target=daemon)
d.daemon = True
n = multiprocessing.Process(name='non-daemon', target=non_daemon)
n.daemon = False
d.start()
time.sleep(1)
n.start()
# d.join()
而代码的输出是:
Starting: daemon 6173
Starting: non-daemon 6174
Exiting: non-daemon 6174
如果末尾的 join() 没有注释,那么输出为:
Starting: daemon 6247
Starting: non-daemon 6248
Exiting: daemon 6247
Exiting: non-daemon 6248
我很困惑b/c守护进程的睡眠时间是 2 秒,而非守护进程是 6 秒。为什么在第一种情况下不打印出 "Exiting" 消息?守护进程应该在非守护进程之前唤醒并打印消息。
本站的解释是这样的:
The output does not include the “Exiting” message from the daemon
process, since all of the non-daemon processes (including the main
program) exit before the daemon process wakes up from its 2 second
sleep.
但我将其更改为守护进程应该在非守护进程之前唤醒。我在这里错过了什么?预先感谢您的帮助。
编辑:忘了说我正在使用 python 2.7 但显然这个问题也在 python 3.x
这是一个有趣的追踪。文档有些误导,因为它们将非守护进程描述为好像它们都是等价的;任何非守护进程的存在都意味着进程 "family" 处于活动状态。 But that's not how it's implemented. 父进程比其他进程"more equal"; multiprocessing
注册一个执行以下操作的 atexit
处理程序:
for p in active_children():
if p.daemon:
info('calling terminate() for daemon %s', p.name)
p._popen.terminate()
for p in active_children():
info('calling join() for process %s', p.name)
p.join()
所以当主进程结束时,它首先 terminate
所有daemon
个子进程,然后 join
所有子进程等待非 daemon
个子进程并清理 daemon
个子进程的资源。
因为它按照这个顺序执行清理,在你的非daemon
Process
start
s 之后,主进程开始清理并强行 terminate
s daemon
Process
.
请注意,修复此问题可以像手动 join
ing 非 daemon
进程一样简单,而不仅仅是 join
ing daemon
进程(这会破坏整点daemon
完全);这会阻止 atexit
处理程序被调用,从而延迟 terminate
daemon
子进程的清理工作。
这可以说是一个错误(这个错误似乎一直存在到 3.5.1;我反驳了自己),但是它是行为错误还是文档错误还有待商榷。
下面的 link 答案可能就在我眼前,但我还是不明白。我确定在有人向我解释之后,达尔文会给我打电话。
示例是 at this link here,尽管我做了一些更改以尝试进行实验并帮助我理解。
代码如下:
import multiprocessing
import time
import sys
def daemon():
p = multiprocessing.current_process()
print 'Starting: ', p.name, p.pid
sys.stdout.flush()
time.sleep(2)
print 'Exiting: ', p.name, p.pid
sys.stdout.flush()
def non_daemon():
p = multiprocessing.current_process()
print 'Starting: ', p.name, p.pid
sys.stdout.flush()
time.sleep(6)
print 'Exiting: ', p.name, p.pid
sys.stdout.flush()
if __name__ == '__main__':
d = multiprocessing.Process(name='daemon', target=daemon)
d.daemon = True
n = multiprocessing.Process(name='non-daemon', target=non_daemon)
n.daemon = False
d.start()
time.sleep(1)
n.start()
# d.join()
而代码的输出是:
Starting: daemon 6173
Starting: non-daemon 6174
Exiting: non-daemon 6174
如果末尾的 join() 没有注释,那么输出为:
Starting: daemon 6247
Starting: non-daemon 6248
Exiting: daemon 6247
Exiting: non-daemon 6248
我很困惑b/c守护进程的睡眠时间是 2 秒,而非守护进程是 6 秒。为什么在第一种情况下不打印出 "Exiting" 消息?守护进程应该在非守护进程之前唤醒并打印消息。
本站的解释是这样的:
The output does not include the “Exiting” message from the daemon process, since all of the non-daemon processes (including the main program) exit before the daemon process wakes up from its 2 second sleep.
但我将其更改为守护进程应该在非守护进程之前唤醒。我在这里错过了什么?预先感谢您的帮助。
编辑:忘了说我正在使用 python 2.7 但显然这个问题也在 python 3.x
这是一个有趣的追踪。文档有些误导,因为它们将非守护进程描述为好像它们都是等价的;任何非守护进程的存在都意味着进程 "family" 处于活动状态。 But that's not how it's implemented. 父进程比其他进程"more equal"; multiprocessing
注册一个执行以下操作的 atexit
处理程序:
for p in active_children():
if p.daemon:
info('calling terminate() for daemon %s', p.name)
p._popen.terminate()
for p in active_children():
info('calling join() for process %s', p.name)
p.join()
所以当主进程结束时,它首先 terminate
所有daemon
个子进程,然后 join
所有子进程等待非 daemon
个子进程并清理 daemon
个子进程的资源。
因为它按照这个顺序执行清理,在你的非daemon
Process
start
s 之后,主进程开始清理并强行 terminate
s daemon
Process
.
请注意,修复此问题可以像手动 join
ing 非 daemon
进程一样简单,而不仅仅是 join
ing daemon
进程(这会破坏整点daemon
完全);这会阻止 atexit
处理程序被调用,从而延迟 terminate
daemon
子进程的清理工作。
这可以说是一个错误(这个错误似乎一直存在到 3.5.1;我反驳了自己),但是它是行为错误还是文档错误还有待商榷。