我正在学习Python中的多处理,而我发现守护进程和非守护进程之间在主进程方面存在奇怪的行为。 我的代码:
import multiprocessing
import time
def worker(name,num):
print name, 'Starting'
time.sleep(num)
print name, 'Exiting'
if __name__ == '__main__':
print 'main starting'
p1=multiprocessing.Process(target=worker, args=("p1",7,))
p2=multiprocessing.Process(target=worker, args=("p2",5,))
p2.daemon=True
p1.start()
p2.start()
time.sleep(4)
print 'main exiting'
我得到的输出是:
main starting
p1 Starting
p2 Starting
main exiting
p1 Exiting
预期产出:
main starting
p1 Starting
p2 Starting
main exiting
p2 Exiting
p1 Exiting
经过几次搜索,我找到this answer并将以下行插入我的代码。
logger = multiprocessing.log_to_stderr(logging.INFO)
我得到的输出是,
main starting
[INFO/p1] child process calling self.run()
p1 Starting
[INFO/p2] child process calling self.run()
p2 Starting
main exiting
[INFO/MainProcess] process shutting down
[INFO/MainProcess] calling terminate() for daemon p2
[INFO/MainProcess] calling join() for process p2
[INFO/MainProcess] calling join() for process p1
p1 Exiting
[INFO/p1] process shutting down
[INFO/p1] process exiting with exitcode 0
根据我的理解,
但是在这里,为什么主进程在p1退出之前试图关闭?
对于上述程序,上述不是正常的时间线吗?
有人可以解释一下这里发生了什么,为什么?
修改
在代码末尾添加行p1.join()
后,我得到以下输出:
main starting
[INFO/Process-1] child process calling self.run()
p1 Starting
[INFO/Process-2] child process calling self.run()
p2 Starting
main exiting
p2 Exiting
[INFO/Process-2] process shutting down
[INFO/Process-2] process exiting with exitcode 0
p1 Exiting
[INFO/Process-1] process shutting down
[INFO/Process-1] process exiting with exitcode 0
[INFO/MainProcess] process shutting down
答案 0 :(得分:1)
当你看到
[INFO/MainProcess] calling join() for process p1
这意味着主要流程还没有退出 - 它在流程关闭,但当然不会关闭,直到join
返回...只有在联合过程完成后才会发生。
所以时间轴确实如你所料 - 但由于join
到p1
是最后一次认为main
进程所做的,所以你看不到在输出中或从中记录。 (主要采取了所有终止触发的行动,但作为一个过程,它一直存在直到那时)。
要验证,在运行此程序时使用(在Unixy系统上)ps
来自另一个终端(可能会有稍长的延迟来帮助您检查):您永远不会看到单个Python进程耗尽此复杂性 - - 直到结束时会有两个(主要和p1)。
答案 1 :(得分:0)
问题最终为守护程序标志和join方法的行为增加了更多等待时间,因此这里将通过一个简单的脚本进行快速解释。
import multiprocessing
import time
import logging
def daemon():
p = multiprocessing.current_process()
print('Starting:', p.name, p.pid, flush=True)
print('---' * 15)
time.sleep(2)
print('===' * 15 + ' < ' + f'Exiting={p.name, p.pid}' + ' > ' + '===' * 15, flush=True)
def non_daemon():
p = multiprocessing.current_process()
print('Starting:', p.name, p.pid, flush=True)
print('---'*15)
print('===' * 15 + ' < ' + f'Exiting={p.name, p.pid}' + ' > ' + '===' * 15, flush=True)
if __name__ == '__main__':
print('==='*15 + ' < ' + 'MAIN PROCESS' + ' > ' + '==='*15)
logger = multiprocessing.log_to_stderr(logging.INFO)
# DAEMON
daemon_proc = multiprocessing.Process(name='MyDaemon', target=daemon)
daemon_proc.daemon = True
# NO-DAEMON
normal_proc = multiprocessing.Process(name='non-daemon', target=non_daemon)
normal_proc.daemon = False
daemon_proc.start()
time.sleep(2)
normal_proc.start()
# daemon_proc.join()
============================================= < MAIN PROCESS > =============================================
Starting: MyDaemon 8448
---------------------------------------------
[INFO/MyDaemon] child process calling self.run()
[INFO/MainProcess] process shutting down
[INFO/MainProcess] calling terminate() for daemon MyDaemon
[INFO/MainProcess] calling join() for process MyDaemon
[INFO/MainProcess] calling join() for process non-daemon
Starting: non-daemon 6688
---------------------------------------------
============================================= < Exiting=('non-daemon', 6688) > =============================================
[INFO/non-daemon] child process calling self.run()
[INFO/non-daemon] process shutting down
[INFO/non-daemon] process exiting with exitcode 0
Process finished with exit code 0
daemon()函数将“耗时” 2秒,因此,当Python到达脚本底部时,程序将关闭,但daemon()不会关闭。
[INFO/MainProcess] calling terminate() for daemon MyDaemon
现在,如果脚本daemon_proc.join()
的最后一行没有被注释。
============================================= < MAIN PROCESS > =============================================
Starting: MyDaemon 13588
---------------------------------------------
[INFO/MyDaemon] child process calling self.run()
============================================= < Exiting=('MyDaemon', 13588) > =============================================
[INFO/MyDaemon] process shutting down
[INFO/MyDaemon] process exiting with exitcode 0
[INFO/MainProcess] process shutting down
[INFO/MainProcess] calling join() for process non-daemon
Starting: non-daemon 13608
---------------------------------------------
============================================= < Exiting=('non-daemon', 13608) > =============================================
[INFO/non-daemon] child process calling self.run()
[INFO/non-daemon] process shutting down
[INFO/non-daemon] process exiting with exitcode 0
Process finished with exit code 0