shashashamti2008
shashashamti2008

Reputation: 2347

Terminating a running script with subprocess

I am using subprocess to execute a python script. I can successfully run the script.

import subprocess
import time

proc = subprocess.Popen(['python', 'test.py', ''], shell=True)
proc.communicate()
time.sleep(10)
proc.terminate()

test.py

import time
while True:
    print("I am inside test.py")
    time.sleep(1)
    

I can see the message I am inside test.py printed every second. However, I am not able to terminate the script while it is still running by proc.terminate().

Could someone kindly help me out?

Upvotes: 0

Views: 1252

Answers (2)

AdamF
AdamF

Reputation: 2950

First things first, don't use a list to pass in the arguments for the subprocess.Popen() if you're using the shell = True!, change the command to string, "python test.py".

Popen.communicate(input=None, timeout=None) is a blocking class method, it shall Interact with process, and Wait for process to terminate and set the returncode attribute.

since your test.py running infinite while loop, he will never return !

you have 2 options to timeout the process proc that you have spawned:

  1. assign the timeout keyword argument in the,e.g. timing the process for 5 seconds, communicate(timeout=5) method. If the process proc does not terminate after timeout seconds, a TimeoutExpired exception will be raised. Catching this exception and retrying communication will not lose any output (in your case you dont need the child outputs, but i will mention this in the example below). ATTENTION The child process is not killed if the timeout expires, so in order to cleanup properly a well-behaved application should kill the child process (proc) and finish communication.
  2. by using the poll method and do the timing by your calling method.

communicate with timeout

try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

poll with time.sleep

proc = subprocess.Popen('python test.py', shell=True)
t=10
while proc.poll() is None and t >= 0:
    print('Still sleeping')
    time.sleep(1)
    t -= 1
proc.kill()

Upvotes: 1

tdelaney
tdelaney

Reputation: 77407

proc.communicate waits for the process to finish unless you include a timeout. Your process doesn't exit and you don't have a timeout so communicate never returns. You could verify that with a print after the call. Instead, add a timeout and catch its exception

import subprocess
import time

proc = subprocess.Popen(['python', 'test.py', ''], shell=True)
try:
    proc.communicate(timeout=10)
except subprocess.TimeoutExpired:
    proc.terminate()

Upvotes: 1

Related Questions