是否有检查子进程是否仍在运行的方法?

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

是否有一种方法可以检查进程是否仍在运行,而不必等待它完成?

118285 次浏览

You could use subprocess.check_output to have a look at your output.

Try this code:

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

Hope this helped!

Ouestion: ... a way to check if a process is still running ...

You can do it for instance:

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

Python » 3.6.1 Documentation popen-objects

Tested with Python:3.4.2

Doing the

myProcessIsRunning = poll() is None

As suggested by the main answer, is the recommended way and the simplest way to check if a process running. (and it works in jython as well)

If you do not have the process instance in hand to check it. Then use the operating system TaskList / Ps processes.

On windows, my command will look as follows:

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

This is essentially doing the same thing as the following command line:

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

And on linux, I do exactly the same using the:

pidStr = str(pid)
commandArguments = ['ps', '-p', pidStr ]

The ps command will already be returning error code 0 / 1 depending on whether the process is found. While on windows you need the find string command.

This is the same approach that is discussed on the following stack overflow thread:

Verify if a process is running using its PID in JAVA

NOTE: If you use this approach, remember to wrap your command call in a try/except:

try:
foundRunningProcess = subprocess.check_output(argumentsArray, **kwargs)
return True
except Exception as err:
return False

Note, be careful if you are developing with VS Code and using pure Python and Jython. On my environment, I was under the illusion that the poll() method did not work because a process that I suspected that must have ended was indeed running. This process had launched Wildfly. And after I had asked for wildfly to stop, the shell was still waiting for user to "Press any key to continue . . .".

In order to finish off this process, in pure python the following code was working:

process.stdin.write(os.linesep)

On jython, I had to fix this code to look as follows:

print >>process.stdin, os.linesep

And with this difference the process did indeed finish. And the jython.poll() started telling me that the process is indeed finished.

As suggested by the other answers None is the designed placeholder for the "return code" when no code has been returned yet by the subprocess.

The documentation for the returncode attribute backs this up (emphasis mine):

The child return code, set by poll() and wait() (and indirectly by communicate()). A None value indicates that the process hasn’t terminated yet.

A negative value -N indicates that the child was terminated by signal N (POSIX only).

An interesting place where this None value occurs is when using the timeout parameter for wait or communicate.

If the process does not terminate after timeout seconds, a TimeoutExpired exception will be raised.

If you catch that exception and check the returncode attribute it will indeed be 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

If you look at the source for subprocess you can see the exception being raised. https://github.com/python/cpython/blob/47be7d0108b4021ede111dbd15a095c725be46b7/Lib/subprocess.py#L1930-L1931

If you search that source for self.returncode is you'll find many uses where the library authors lean on that None return code design to infer if an app is running or not running. The returncode attribute is initialized to None and only ever changes in a few spots, the main flow in invocations to _handle_exitstatus to pass on the actual return code.