Python:如何确定子进程的子进程已经全部运行完毕



我正在尝试从Python脚本中检测安装程序何时完成执行。具体来说,应用程序是Oracle 10gR2数据库。目前,我正在使用Popen的子流程模块。理想情况下,我只需使用wait()方法来等待安装完成执行,然而,文档中的命令实际上会产生子进程来处理实际的安装。以下是一些失败代码的示例代码:

import subprocess
OUI_DATABASE_10GR2_SUBPROCESS = ['sudo',
                                 '-u',
                                 'oracle',
                                 os.path.join(DATABASE_10GR2_TMP_PATH,
                                              'database',
                                              'runInstaller'),
                                 '-ignoreSysPrereqs',
                                 '-silent',
                                 '-noconfig',
                                 '-responseFile '+ORACLE_DATABASE_10GR2_SILENT_RESPONSE]
oracle_subprocess = subprocess.Popen(OUI_DATABASE_10GR2_SUBPROCESS)
oracle_subprocess.wait()

这里还有一个类似的问题:从python中杀死包括其子进程的子进程,但所选的答案并没有解决子进程问题,而是指示用户直接调用要等待的应用程序。我正在寻找一个特定的解决方案,它将等待子流程的所有子进程。如果存在数量未知的子流程,该怎么办?我将选择解决等待所有子进程完成问题的答案。

更清楚地说明失败:子进程在wait()命令之后继续执行,因为该命令只等待顶级进程(在本例中为"sudo")。以下是此问题中已知子进程的简单示意图:Python子流程模块->Sudo->runInstaller->java->(未知)

好的,这里有一个只有在Unix下才能使用的技巧。它类似于这个问题的答案之一:确保子流程在退出Python程序时是死的。其想法是创建一个新的流程组。然后,您可以等待组中的所有进程终止。

pid = os.fork()
if pid == 0:
    os.setpgrp()
    oracle_subprocess = subprocess.Popen(OUI_DATABASE_10GR2_SUBPROCESS)
    oracle_subprocess.wait()
    os._exit(0)
else:
    os.waitpid(-pid)

我还没有对此进行测试。它创建了一个额外的子流程作为流程组的领导者,但避免这样做(我认为)要复杂得多。

我发现这个网页也很有用。http://code.activestate.com/recipes/278731-creating-a-daemon-the-python-way/

您可以使用os.waitpid,将pid设置为-1,这将等待当前流程的所有子流程,直到它们完成:

import os
import sys
import subprocess

proc = subprocess.Popen([sys.executable,
                         '-c',
                         'import subprocess;'
                         'subprocess.Popen("sleep 5", shell=True).wait()'])
pid, status = os.waitpid(-1, 0)
print pid, status

这是分叉的不同子流程的pstree <pid>的结果:

python───python───sh───sleep

希望这能有所帮助:)

查看以下链接http://www.oracle-wiki.net/startdocsruninstaller详细说明了可以用于runInstaller命令的标志。

这个标志肯定适用于11gR2,但我还没有一个10g数据库来为该版本打包的runInstaller试用这个标志。

问候

我所看到的每一个地方似乎都在说,在一般情况下都不可能解决这个问题。我创建了一个名为"pidmon"的库,它结合了Windows和Linux的一些答案,可以满足您的需求。

我打算把它清理干净,放在github上,可能被称为"pidmon"或类似的东西。如果/当我得到链接时,我会发布它

编辑:可在http://github.com/dbarnett/python-pidmon.

我制作了一个特殊的waitpid函数,它接受graft_func参数,这样你就可以松散地定义当它们不是直接子进程时,你想等待什么样的进程:

import pidmon
pidmon.waitpid(oracle_subprocess.pid, recursive=True,
        graft_func=(lambda p: p.name == '???' and p.parent.pid == ???))

或者,作为一种霰弹枪式方法,只需等待自调用waitpid以来启动的任何进程再次停止,执行:

import pidmon
pidmon.waitpid(oracle_subprocess.pid, graft_func=(lambda p: True))

请注意,这在Windows上几乎没有测试过,在Windows上似乎很慢(但我有没有提到它在github上很容易分叉?)。这至少应该让你开始,如果它对你有用,我对如何优化它有很多想法。

相关内容

  • 没有找到相关文章

最新更新