gpt4 book ai didi

python - 为什么在 python 中主进程退出时子进程 (daemon=True) 不退出?

转载 作者:行者123 更新时间:2023-12-01 02:45:13 25 4
gpt4 key购买 nike

官方对python multiprocessing中daemon标志的解释如下:

When a process exits, it attempts to terminate all of its daemonic child processes.

据我了解,父进程在退出时会杀死其守护进程标志设置为 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个子进程和1个主进程。我杀死了主进程,但 4 个 child 没有退出。

既然守护进程设置为真,为什么它们没有被 main 终止?

最佳答案

注意事项:

  • xrange 的使用意味着 Python 2
  • xrange(1, 4) 将产生 3 个值而不是 4 个(因此,只有 3 个 child )

事情并不是这样运作的。文档 ( [Python 2.Docs]: multiprocessing - daemon) 应该更具体一些。

事情是 multiprocessing 注册一个 cleanup 函数 以在退出时杀死它的所有 deamonic child 。这是通过 [Python 2.Docs]: atexit - Exit handlers 完成的:

Note: The functions registered via this module are not called when the program is killed by a signal not handled by Python, when a Python fatal internal error is detected, or when os._exit() is called.

您不处理 TERM 信号(默认情况下由 kill 命令发送),因此清理函数不会被主进程调用(留下它的子进程)运行)。

我修改了您的代码以更好地说明该行为。

code00.py:

#!/usr/bin/env python2

import sys
import multiprocessing
import os
import time


print_text_pattern = "Output from process {0:s} - pid: {1:d}, ppid: {2:d}"


def child(name):
while True:
print(print_text_pattern.format(name, os.getpid(), os.getppid()))
time.sleep(1)


def main():
procs = list()
for x in xrange(1, 3):
proc_name = "Child{0:d}".format(x)
proc = multiprocessing.Process(target=child, args=(proc_name,))
proc.daemon = True #x % 2 == 0
print("Process {0:s} daemon: {1:}".format(proc_name, proc.daemon))
procs.append(proc)

for proc in procs:
proc.start()

counter = 0
while counter < 3:
print(print_text_pattern.format("Main", os.getpid(), os.getppid()))
time.sleep(1)
counter += 1


if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main()
print("\nDone.")

注意事项:

  • 稍微改变了子进程的生成方式:所有子进程都是在第一时间创建的st,然后才开始
  • 添加了来自每个进程的一些 print 调用,以跟踪它们在 stdout 中的事件 - 还添加了一些 time.sleep 调用(1 秒), 以避免产生过多的输出
  • 最重要 - 主进程不再永远运行。在某些时候它会优雅地退出(在 3 个周期后 - 由于 counter 变量),并且当我之前提到的行为开始时。
    这也可以通过拦截 < em>TERM 信号(以及其他可以由 kill 命令显式发送的信号)然后执行清理 - 这样子进程也会在杀死主进程时被 kill - 但那更复杂
  • 我稍微简化了一些事情,所以只产生了 2 个 child
  • 移动 main 函数(用于结构)中的所有内容,包含在 if __name__ == "__main__": 条件中,因此如果您 导入模块
  • 为每个 child 赋予不同的值 proc.daemon 然后监控输出和 ps -ef | grep "code00.py" 输出
  • child 函数添加了一个参数(name),但这仅用于显示目的

输出:

[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow]> python2 code00.py
Python 2.7.12 (default, Oct 8 2019, 14:14:10) [GCC 5.4.0 20160609] 64bit on linux2

Process Child1 daemon: True
Process Child2 daemon: True
Output from process Main - pid: 1433, ppid: 1209
Output from process Child1 - pid: 1434, ppid: 1433
Output from process Child2 - pid: 1435, ppid: 1433
Output from process Main - pid: 1433, ppid: 1209
Output from process Child2 - pid: 1435, ppid: 1433
Output from process Child1 - pid: 1434, ppid: 1433
Output from process Main - pid: 1433, ppid: 1209
Output from process Child1 - pid: 1434, ppid: 1433
Output from process Child2 - pid: 1435, ppid: 1433
Output from process Child1 - pid: 1434, ppid: 1433
Output from process Child2 - pid: 1435, ppid: 1433

Done.

关于python - 为什么在 python 中主进程退出时子进程 (daemon=True) 不退出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49604997/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com