9

Possible Duplicate:
subprocess with timeout

What is the easiest way to do the following in Python:

  • Run an external process
  • Capture stdout in a string, stderr, and exit status
  • Set a timeout.

I would like something like this:

import proc

try:
    status, stdout, stderr = proc.run(["ls", "-l"], timeout=10)
except proc.Timeout:
    print "failed"
4
  • 2
    Just so we know where you're starting from, have you considered the subprocess module? docs.python.org/library/subprocess.html Commented Oct 12, 2009 at 19:11
  • no - looks like that is a big leap forwards Commented Oct 12, 2009 at 19:15
  • 1
    subprocess' Popen.communicate with timeout, similar question: stackoverflow.com/questions/1191374/subprocess-with-timeout Commented Oct 12, 2009 at 19:15
  • @Mark: good catch, marked as duplicate. Commented Oct 12, 2009 at 19:18

2 Answers 2

13

I hate doing the work by myself. Just copy this into your proc.py module.

import subprocess
import time
import sys

class Timeout(Exception):
    pass

def run(command, timeout=10):
    proc = subprocess.Popen(command, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    poll_seconds = .250
    deadline = time.time()+timeout
    while time.time() < deadline and proc.poll() == None:
        time.sleep(poll_seconds)

    if proc.poll() == None:
        if float(sys.version[:3]) >= 2.6:
            proc.terminate()
        raise Timeout()

    stdout, stderr = proc.communicate()
    return stdout, stderr, proc.returncode

if __name__=="__main__":
    print run(["ls", "-l"])
    print run(["find", "/"], timeout=3) #should timeout
Sign up to request clarification or add additional context in comments.

3 Comments

This version might timeout due to pipe buffer overflow (when stdout or stderr ~64K).
If the command times out, you won't get any output generated up to the timeout.
print run(["ping www.redicecn.com"], timeout=10),the script threw out Timeout exception, but the ping process was still running.
12

Note on linux with coreutils >= 7.0 you can prepend timeout to the command like:

timeout 1 sleep 1000

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.