有没有办法检查子进程是否仍在运行?

时间:2017-04-07 09:25:50

标签: python subprocess

我在Python中使用subprocess.Popen启动了许多子进程。 我想检查一个这样的过程是否已经完成。我发现了两种检查子进程状态的方法,但两者似乎都迫使进程完成。 一个是使用process.communicate()并打印返回码,如here所述。 另一个是简单地调用process.wait()并检查它是否返回0。

有没有办法检查进程是否仍在运行而不等待它完成?

4 个答案:

答案 0 :(得分:33)

  

Ouestion :...检查进程是否仍在运行的方法......

你可以这样做:

p = subprocess.Popen(...
"""
A None value indicates that the process hasn't terminated yet.
"""
poll = p.poll()
if poll == None:
  # p.subprocess is alive

Python » 3.6.1 Documentation popen-objects

使用Python测试:3.4.2

答案 1 :(得分:3)

执行

myProcessIsRunning = poll() is None 

正如主要答案所建议的那样,是推荐的方法和最简单的方法来检查一个进程是否正在运行。 (它也适用于jython)

如果您没有手头的流程实例来检查它。 然后使用操作系统TaskList / Ps进程。

在Windows上,我的命令如下:

filterByPid = "PID eq %s" % pid
        pidStr = str(pid)
        commandArguments = ['cmd', '/c', "tasklist", "/FI", filterByPid, "|", "findstr",  pidStr ]

这基本上与以下命令行做同样的事情:

cmd /c "tasklist /FI "PID eq 55588" | findstr 55588"

在Linux上,我使用:

完全相同
pidStr = str(pid)
commandArguments = ['ps', '-p', pidStr ]

ps命令已经返回错误代码0/1,具体取决于是否找到进程。在Windows上,您需要find string命令。

这与followig stack overflow thread讨论的方法相同:

Verify if a process is running using its PID in JAVA

注意: 如果您使用此方法,请记住将命令调用包装在中     尝试:       foundRunningProcess = subprocess.check_output(argumentsArray,** kwargs)       返回True     除了例外错误:       返回False

注意,如果您使用VS Code进行开发并使用纯Python和Jython,请务必小心。 在我的环境中,我认为poll()方法不起作用,因为我怀疑必须已经结束的进程确实正在运行。 这个过程推出了Wildfly。在我要求野蝇停止后,外壳仍在等待用户“按任意键继续......”。

为了完成这个过程,在纯python中,以下代码正在运行:

process.stdin.write(os.linesep)

在jython上,我必须修改此代码,如下所示:

print >>process.stdin, os.linesep

由于这种差异,这个过程确实完成了。 并且jython.poll()开始告诉我该过程确实已经完成。

答案 2 :(得分:0)

您可以使用subprocess.check_output来查看输出。

试试这段代码:

import subprocess
subprocess.check_output(['your command here'], shell=True, stderr=subprocess.STDOUT)

希望这有帮助!

答案 3 :(得分:0)

如其他答案所建议,None是子进程尚未返回任何代码时为“返回代码”设计的占位符。

returncode属性的文档对此进行了支持(强调我的意思):

子返回码,由poll()wait()设置(间接由communicate()设置)。 None值表示该过程尚未终止

负值-N表示该子对象已被信号N终止(仅适用于POSIX)。

出现None值的一个有趣地方是将waitcommunicatetimeout参数使用。

如果超时秒后进程仍未终止,则会引发TimeoutExpired异常。

如果您捕获该异常并检查returncode属性,则其确实为None

import subprocess
with subprocess.Popen(['ping','127.0.0.1']) as p:
    try:
        p.wait(timeout=3)
    except subprocess.TimeoutExpired:
        assert p.returncode is None

如果查看子流程的源代码,则可以看到正在引发的异常。 https://github.com/python/cpython/blob/47be7d0108b4021ede111dbd15a095c725be46b7/Lib/subprocess.py#L1930-L1931

如果您在源中搜索self.returncode is,则会发现许多用途,库作者依靠该None返回代码设计来推断应用程序是否正在运行。 returncode属性是initializedNone,并且仅在几个位置发生变化,这是对_handle_exitstatus的调用的主要流程,以传递实际的返回代码。