Search code examples
pythontimeoutpipesubprocesspopen

Python subprocess timeout?


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

Something like this:

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


Solution

  • 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.