Python subprocess timeout?

sultan picture sultan · Sep 17, 2010 · Viewed 34.8k times · Source

Is there any argument or options to setup a timeout for Python's subprocess.Popen method?

Something like this:

subprocess.Popen(['..'], ..., timeout=20) ?

Answer

dvntehn00bz picture dvntehn00bz · Nov 13, 2012

I would advise taking a look at the Timer class in the threading module. I used it to implement a timeout for a Popen.

First, create a callback:

def timeout( p ):
    if p.poll() is None:
        print 'Error: process taking too long to complete--terminating'
        p.kill()

Then open the process:

proc = Popen( ... )

Then create a timer that will call the callback, passing the process to it.

t = threading.Timer( 10.0, timeout, [proc] )
t.start()
t.join()

Somewhere later in the program, you may want to add the line:

t.cancel()

Otherwise, the python program will keep running until the timer has finished running.

EDIT: I was advised that there is a race condition that the subprocess p may terminate between the p.poll() and p.kill() calls. I believe the following code can fix that:

import errno

def timeout( p ):
    if p.poll() is None:
        try:
            p.kill()
            print 'Error: process taking too long to complete--terminating'
        except OSError as e:
            if e.errno != errno.ESRCH:
                raise

Though you may want to clean the exception handling to specifically handle just the particular exception that occurs when the subprocess has already terminated normally.