1

I use sub.Popen in Python2.7

But, Python3 has timeout but, Python2.7 can't it.

it is my snippet.

proc = sub.Popen(['some command', 'some params'], stdout=sub.PIPE)    

try:
    for row in proc.stdout:
        print row.rstrip()   # process here
        result = str(row.rstrip())
        count += 1
        if count > 10:
            break
except:
    print 'tcpdump error'
    proc.terminate()

How to set timeout to it.

shinriyo
  • 344
  • 3
  • 17

2 Answers2

1

Based on this blog post code with a couple of changes you can use threading.Thread:

from threading import Thread
from subprocess import PIPE, Popen


def proc_timeout(secs, *args):
    proc = Popen(args, stderr=PIPE, stdout=PIPE)
    proc_thread = Thread(target=proc.wait)
    proc_thread.start()
    proc_thread.join(secs)
    if proc_thread.is_alive():
        try:
            proc.kill()
        except OSError:
            return proc.returncode
        print('Process #{} killed after {} seconds'.format(proc.pid, secs))
    return proc

You should only catch specific exceptions in your try/except, don't try to catch them all.

Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • @shinriyo, no worries, not overly tested the code but should do what you want. It will raise a SubprocessTimeoutError if the command does not return within secs – Padraic Cunningham Mar 28 '15 at 14:20
  • Hey, Managed to use this, but I can't find a way to record STDOUT with this. ``proc = Popen(args, stderr=PIPE, stdout=PIPE)`` Won't let you read from stdout. It makes me get: an error reading from closed file. Any way around that? – GuySoft Apr 24 '15 at 12:25
  • How are you running it, I edited the answer removing the raise as you probably always want the output before the timeout – Padraic Cunningham Apr 24 '15 at 13:46
  • I was actually using the raise. Looks like it works. Great! – GuySoft Apr 25 '15 at 19:01
0

If you are using linux (or possibly other unix derivatives) you could use the timeout command. For example:

subprocess.Popen(['timeout', '5', 'sleep', '20']).wait()

will timeout after 5 seconds. proc.communicate() should also work with this method.

Other alternatives can be found in this related question: Using module 'subprocess' with timeout

Community
  • 1
  • 1
mhawke
  • 84,695
  • 9
  • 117
  • 138