Python:如何判断子进程的所有子进程已完成运行
我正在尝试在一个Python脚本中检测安装程序何时执行完毕。具体来说,我要处理的是Oracle 10gR2数据库。目前,我使用的是subprocess模块中的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 subprocess模块 -> Sudo -> runInstaller -> java -> (未知)
4 个回答
请查看以下链接 http://www.oracle-wiki.net/startdocsruninstaller,里面详细介绍了一个可以用于runInstaller命令的标志。
这个标志在11gR2版本中肯定是可以用的,但我没有10g版本的数据库来测试这个标志在那个版本的runInstaller中的效果。
祝好
你可以直接使用 os.waitpid,把进程ID(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
希望这能帮到你 :)
好的,这里有一个技巧,只在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/