来自python的产卵过程

Posted

技术标签:

【中文标题】来自python的产卵过程【英文标题】:spawning process from python 【发布时间】:2010-11-01 14:57:34 【问题描述】:

我正在从这样的网络应用程序生成一个长时间运行的脚本:

os.spawnle(os.P_NOWAIT, "../bin/producenotify.py", "producenotify.py", "xx",os.environ)

脚本成功生成并运行,但在它结束之前,我无法释放 Web 应用程序使用的端口,或者换句话说,我无法重新启动 Web 应用程序。如何生成一个进程并使其完全独立于 Web 应用程序?

这是在 linux 操作系统上。

【问题讨论】:

你为什么不使用 subprocess.Popen 来做到这一点? S. Lott:在执行 subprocess.Popen 之后,我可以杀死/重新启动 Web 应用程序/父进程吗?谢谢 【参考方案1】:

正如@mark 澄清的那样,它是一个 Linux 系统,通过遵循这个recipe,脚本可以很容易地使自己完全独立,即一个守护进程。 (您也可以在 os.fork 之后在父进程中执行此操作,然后才在子进程 os.exec... 之后执行此操作。

编辑:澄清@mark对我的回答的评论的一些细节:根据食谱食谱“守护”进程不需要超级用户权限,也不需要更改当前工作目录(尽管配方中的代码确实做到了这一点,而且更多,这不是关键部分——而是fork_exitsetsid 调用的正确逻辑顺序)。不以e 结尾的各种os.exec... 变体 使用父进程的环境,因此这部分也很简单——参见Python online docs。

解决其他人的 cmets 和答案中提出的建议:我相信 subprocessmultiprocessing 本身不会守护子进程,这似乎是 @mark 需要的;脚本可以自己完成,但由于 一些 代码必须执行 forks 和 setsid,所以在我看来,将所有产卵都保持在低级平面上而不是而不是在运行过程中混合一些高级和一些低级代码。

在上面的 URL 中,这是一个大大简化和简化的配方版本,专为在父进程中调用以生成一个守护进程子进程而设计——这样,代码也可以用于执行非 Python 可执行文件。如给定的那样,代码应该满足@mark 解释的需求,当然它可以通过多种方式进行定制——我强烈建议阅读原始配方及其 cmets 和讨论,以及它推荐的书籍,以获取更多信息。

import os
import sys

def spawnDaemon(path_to_executable, *args)
    """Spawn a completely detached subprocess (i.e., a daemon).

    E.g. for mark:
    spawnDaemon("../bin/producenotify.py", "producenotify.py", "xx")
    """
    # fork the first time (to make a non-session-leader child process)
    try:
        pid = os.fork()
    except OSError, e:
        raise RuntimeError("1st fork failed: %s [%d]" % (e.strerror, e.errno))
    if pid != 0:
        # parent (calling) process is all done
        return

    # detach from controlling terminal (to make child a session-leader)
    os.setsid()
    try:
        pid = os.fork()
    except OSError, e:
        raise RuntimeError("2nd fork failed: %s [%d]" % (e.strerror, e.errno))
        raise Exception, "%s [%d]" % (e.strerror, e.errno)
    if pid != 0:
        # child process is all done
        os._exit(0)

    # grandchild process now non-session-leader, detached from parent
    # grandchild process must now close all open files
    try:
        maxfd = os.sysconf("SC_OPEN_MAX")
    except (AttributeError, ValueError):
        maxfd = 1024

    for fd in range(maxfd):
        try:
           os.close(fd)
        except OSError: # ERROR, fd wasn't open to begin with (ignored)
           pass

    # redirect stdin, stdout and stderr to /dev/null
    os.open(os.devnull, os.O_RDWR)  # standard input (0)
    os.dup2(0, 1)
    os.dup2(0, 2)

    # and finally let's execute the executable for the daemon!
    try:
      os.execv(path_to_executable, args)
    except Exception, e:
      # oops, we're cut off from the world, let's just give up
      os._exit(255)

【讨论】:

alex,它是一个类unix系统。软呢Linux。 Web 应用程序没有超级用户权限。那是问题吗?守护进程也应该与 webapp 具有相同的工作目录和环境变量。我如何实现这些?谢谢 alex, tx 进行澄清。我检查了食谱,这有点令人困惑。该代码在父 Web 应用程序中吗?或者它是否进入要生成的新脚本?再次感谢! 我可以在函数结束时将守护进程pid返回给函数调用者吗? 为什么会有两个连续的 raise 语句?我一直认为第二个永远不会被执行。 在我的应用程序中,第一个孩子用 Alex 的代码变成了僵尸。在“返回”之前,我插入了os.waitpid(pid, 0),这对我有用。但如果有人能证实这一点,我将不胜感激。【参考方案2】:

您可以使用多处理库来生成进程。此处显示了一个基本示例:

from multiprocessing import Process

def f(name):
    print 'hello', name

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()

【讨论】:

这有一个问题,就是在子进程完成之前无法杀死主进程。谢谢! 注意 multiprocessing 库已添加到 Python 2.6。这是文档docs.python.org/library/multiprocessing.html @mark 如果你想让主进程立即终止而不等待子进程,你只需要将子进程标记为守护进程。 @CadentOrange “此外,这些不是 Unix 守护进程或服务,它们是正常进程,如果非守护进程退出,它们将被终止(而不是加入)。” (文档)不是说在这种情况下会杀死守护进程吗? 这不是我说的吗?如果将子进程标记为守护进程,则子进程将在父进程(即非守护进程)终止时立即终止。

以上是关于来自python的产卵过程的主要内容,如果未能解决你的问题,请参考以下文章

Python3 - 无法根据来自对象检测过程的输入正确启动输出设备

苹果在蛇内产卵

苹果在蛇里面产卵

了解蝗虫用户和产卵率

Python编译/解释过程

船产卵(Roblox Studio)