I am running some shell scripts with the subprocess module in python. If the shell scripts is running to long, I like to kill the subprocess. I thought it will be enough if I am passing the timeout=30
to my run(..)
statement.
Here is the code:
try:
result=run(['utilities/shell_scripts/{0} {1} {2}'.format(
self.language_conf[key][1], self.proc_dir, config.main_file)],
shell=True,
check=True,
stdout=PIPE,
stderr=PIPE,
universal_newlines=True,
timeout=30,
bufsize=100)
except TimeoutExpired as timeout:
I have tested this call with some shell scripts that runs 120s. I expected the subprocess to be killed after 30s, but in fact the process is finishing the 120s script and than raises the Timeout Exception. Now the Question how can I kill the subprocess by timeout?
The documentation explicitly states that the process should be killed:
from the docs for
subprocess.run
:But in your case you're using
shell=True
, and I've seen issues like that before, because the blocking process is a child of the shell process.I don't think you need
shell=True
if you decompose your arguments properly and your scripts have the proper shebang. You could try this:note that I can reproduce this issue very easily on Windows (using
Popen
, but it's the same thing):=> notepad stays open, probably because it manages to detach from the parent shell process.
=> notepad closes after 1 second
Funnily enough, if you remove
time.sleep()
,kill()
works even withshell=True
probably because it successfully kills the shell which is launchingnotepad
.I'm not saying you have exactly the same issue, I'm just demonstrating that
shell=True
is evil for many reasons, and not being able to kill/timeout the process is one more reason.However, if you need
shell=True
for a reason, you can usepsutil
to kill all the children in the end. In that case, it's better to usePopen
so you get the process id directly:(source: how to kill process and child processes from python?)
that example kills the notepad instance as well.