Here's the Python code to run an arbitrary command returning its stdout
data, or raise an exception on non-zero exit codes:
proc = subprocess.Popen(
cmd,
stderr=subprocess.STDOUT, # Merge stdout and stderr
stdout=subprocess.PIPE,
shell=True)
communicate
is used to wait for the process to exit:
stdoutdata, stderrdata = proc.communicate()
The subprocess
module does not support timeout--ability to kill a process running for more than X number of seconds--therefore, communicate
may take forever to run.
What is the simplest way to implement timeouts in a Python program meant to run on Windows and Linux?
There's an idea to subclass the Popen class and extend it with some simple method decorators. Let's call it ExpirablePopen.
Was just trying to write something simpler.
In Python 3.3+:
output
is a byte string that contains command's merged stdout, stderr data.This code raises
CalledProcessError
on non-zero exit status as specified in the question's text unlikeproc.communicate()
method.I've removed
shell=True
because it is often used unnecessarily. You can always add it back ifcmd
indeed requires it. If you addshell=True
i.e., if the child process spawns its own descendants;check_output()
can return much later than the timeout indicates, see Subprocess timeout failure.The timeout feature is available on Python 2.x via the
subprocess32
backport of the 3.2+ subprocess module.Although I haven't looked at it extensively, this decorator I found at ActiveState seems to be quite useful for this sort of thing. Along with
subprocess.Popen(..., close_fds=True)
, at least I'm ready for shell-scripting in Python.I've modified sussudio answer. Now function returns: (
returncode
,stdout
,stderr
,timeout
) -stdout
andstderr
is decoded to utf-8 stringI added the solution with threading from
jcollado
to my Python module easyprocess.Install:
Example: