I want to use a timeout on a subprocess
from subprocess32 import check_output
output = check_output("sleep 30", shell=True, timeout=1)
Unfortunately, whilst this raises a timeout error, it does so after 30 seconds. It seems that check_output cannot interrupt the shell command.
What can I do on on the Python side to stop this? I suspect that subprocess32 fails to kill the timed out process.
Update for Python 3.6.
This is still happening but I have tested a lot of combinations of
check_output
,communicate
andrun
methods and now I have a clear knowledge about where is the bug and how to avoid it in a easy way on Python 3.5 and Python 3.6.My conclusion: It happens when you mix the use
shell=True
and anyPIPE
onstdout
,stderr
orstdin
parameters (used inPopen
andrun
methods).Be careful:
check_output
usesPIPE
inside. If you look at the code inside on Python 3.6 it is basically a call torun
withstdout=PIPE
: https://github.com/python/cpython/blob/ae011e00189d9083dd84c357718264e24fe77314/Lib/subprocess.py#L335So, to solve @innisfree problem on Python 3.5 or 3.6 just do this:
And for other cases, just avoid mixing
shell=True
andPIPE
, keeping in mind thatcheck_output
usesPIPE
.check_output()
with timeout is essentially:There are two issues:
.communicate()
may wait for descendant processes, not just for the immediate child, see Python subprocess .check_call vs .check_outputprocess.kill()
might not kill the whole process tree, see How to terminate a python subprocess launched with shell=TrueIt leads to the behaviour that you observed: the
TimeoutExpired
happens in a second, the shell is killed, butcheck_output()
returns only in 30 seconds after the grandchildsleep
process exits.To workaround the issues, kill the whole process tree (all subprocesses that belong to the same group):
Output