Python中设置daemon=True的子进程为何在主进程退出时不终止?
我懂你的困惑——官方文档明确说父进程退出时会尝试终止所有守护子进程,但你自己写的测试代码却没得到预期结果,对吧?咱们先把你的代码补全,再一步步拆解问题出在哪。
首先,先把你的测试代码补全(我猜你是漏写了proc.start(),而且可能没加Windows下必须的入口保护):
import multiprocessing import time def child(): while True: print(f"子进程 {multiprocessing.current_process().pid} 运行中...") time.sleep(1) if __name__ == "__main__": for x in range(1, 4): proc = multiprocessing.Process(target=child, args=()) proc.daemon = True proc.start() print("父进程即将退出") time.sleep(2)
接下来,咱们分析可能导致你结果不符的几个常见原因:
缺少
if __name__ == "__main__":保护:在Windows系统下,multiprocessing模块通过创建新进程重新导入脚本的方式启动子进程,如果没有这个入口保护,子进程会重复执行整个脚本,导致额外的进程被创建,让你误以为原来的守护进程没被终止。这是Windows下使用multiprocessing的必加项。父进程未正常退出:官方文档里的“尝试终止”是建立在父进程正常退出的基础上的。如果父进程是被强制杀死的(比如Unix下用
kill -9,Windows下强制结束任务),它根本没机会向守护子进程发送终止信号,这些子进程会变成孤儿进程,被系统的init/systemd进程接管,继续运行。没给父进程足够的终止时间:父进程退出时,需要一点时间来给守护子进程发送终止信号并等待它们结束。如果你在父进程刚退出就立刻查看进程状态,可能会看到子进程还没来得及被终止,过几秒再查就会发现它们已经消失了。
再回头看官方文档的描述:
当一个进程退出时,它会尝试终止所有守护子进程。
这里的“尝试”是关键:父进程会向守护子进程发送终止信号(Unix是SIGTERM,Windows是TerminateProcess),对于像你的死循环这种没有阻塞系统调用的子进程,会很快响应信号并终止;但如果子进程卡在无法被中断的系统调用里,可能需要额外处理,但这种情况比较少见。
你可以运行上面补全后的代码试试:父进程等待2秒后退出,子进程的打印会立刻停止,用进程管理工具查看的话,那些守护子进程也会跟着父进程一起消失。
内容的提问来源于stack exchange,提问作者Kramer Li

