Kill children of Python subprocess after subprocess.TimeoutExpired is thrown

Viewed 1733

I am calling a shell script fom within Python, that spawns multiple child processes. I want to terminate that process and all of its children, if it did not finish after two minutes.

Is there any way I can do that with subprocess.run or do I have to go back to using Popen? Since run is blocking, I am not able to save the pid somewhere to kill the children in an extra command. A short code example:

try:
    subprocess.run(["my_shell_script"], stderr=subprocess.STDOUT, timeout=120)
except subprocess.TimeoutExpired:                                                                      
    print("Timeout during execution")
2 Answers

This problem was reported as a bug to the Python developers. It seems to happen specifically when stderr or stdout is redirected. Here is a more correct version of @Tanu's code.

import subprocess as sp

try:
    proc = sp.Popen(['ls', '-l'], stdout=sp.PIPE, stderr=sp.PIPE)
    outs, errs = proc.communicate(timeout=120)
except sp.TimeoutExpired:
    proc.terminate()

Popen doesn't accept timeout as a parameter. It must be passed to communicate. On Posix OSs, terminate is more gentle than kill, in that it reduces the risk of creating zombie processes.

Related