11

从 python 终端,我运行如下命令,生成一个长时间运行的子进程:

from multiprocessing.process import Process
Process(target=LONG_RUNNING_FUNCTION).start()

此命令返回,我可以在 python 终端中执行其他操作,但孩子打印的任何内容仍会打印到我的 python 终端会话中。

当我退出终端(使用exitCTRL+ D)时,退出命令会挂起。如果我点击CTRL+C,则子进程将终止。

如果我手动终止 python 终端进程(通过 posixkill命令),子进程将变成孤立的,并继续运行,其输出可能被丢弃。

如果我使用 运行此代码python -c,它会等待子进程终止,然后CTRL+C杀死父子进程。

当父母终止时,python 的哪些运行配置会杀死孩子?特别是,如果 python-mod_wsgi-apache 网络服务器产生子进程然后重新启动,这些子进程会被杀死吗?

[顺便说一句,分离从终端产生的子进程的正确方法是什么?有没有比以下更优雅的方法:Deliberately make an orphan process in python ]

更新:multiprocessing.Process当 apache 重新启动时,由在 apache 下运行的 web 服务器生成的 python 子进程不会被杀死。

4

1 回答 1

20

这与您如何调用 python 无关。multiprocessing这是模块的一个功能。当您导入该模块时,将向父进程添加一个退出处理程序,该处理程序在允许父进程退出之前调用通过创建的所有子进程join()Process对象multiprocessing.Process。如果您打算以这种方式启动子进程,那么如果不破解模块内部,就无法避免给您带来麻烦的行为。

如果您想启动一个能够比父进程寿命更长的进程,那么使用subprocess.Popen. 如果孩子以这种方式开始,则父母在退出之前不会尝试加入孩子,而是会立即退出,留下一个孤儿:

>>> from subprocess import Popen
>>> Popen(["sleep", "100"])
<subprocess.Popen object at 0x10d3fedd0>
>>> exit()
alp:~ $ ps -opid,ppid,command | grep sleep | grep -v grep
37979     1 sleep 100

您使用multiprocessing而不是有特殊原因subprocess吗?前者不打算用于创建旨在比父进程寿命更长的子进程;它用于创建子进程来完成可以在 CPU 之间有效并行化的工作,作为绕过Global Interpreter Lock的一种方式。multiprocessing(出于讨论的目的,我忽略了 的分布式功能。)multiprocessing因此通常用于如果没有 GIL 的情况下,您将使用线程。(注意,在这方面,multiprocessing模块的 API 是在模块的 API 之后建模的threading。)

对于您帖子末尾的具体问题:(1)当父母终止时,python 没有任何责任杀死孩子。只有当父进程在退出之前将其杀死(或者整个进程组都被杀死)时,Web 服务器的子进程才会被杀死。(2) 您链接到的方法看起来像是在尝试复制守护进程而不知道这样做的标准习语。有许多用于创建守护进程的包;您应该改用其中之一。

于 2014-02-09T23:14:49.747 回答