James King
James King

Reputation: 1614

Terminate Python Process in a Limited Time

Take a look at this simple python code with Process:

from multiprocessing import Process
import time

def f(name):
    time.sleep(100)
    print 'hello', name

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()#Has to be terminated in 5 seconds
    #p.join()
    print "This Needs to be Printed Immediately"

I guess I am looking for a function like p.start(timeout).

I want to terminate the p process if it has not self-finished in like 5 seconds. How can I do that? There seems to be no such function.

If p.join() is uncommented, the following print line will have to wait 100 seconds and can not be 'Printed Immediately'.But I want it be done immediately so the p.join() has to be commented out.

Upvotes: 1

Views: 1006

Answers (5)

miraculixx
miraculixx

Reputation: 10379

Why not use the timeout option of Process.join(), as in:

import sys
...
if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()#Has to be terminated in 5 seconds
    # print immediately and flush output 
    print "This Needs to be Printed Immediately"
    sys.stdout.flush()
    p.join(5)
    if p.is_alive():
       p.terminate()

Upvotes: 0

Christopher
Christopher

Reputation: 179

Try something like this:

def run_process_with_timeout(timeout, target, args):
    p = Process(target=target, args=args)
    running = False
    second = int(time.strftime("%S"))
    if second+timeout > 59:
        second = (second+timeout)-60
    else:
        second = second+timeout
    print second
    while second > int(time.strftime("%S")):
        if running == False:
            p.start()
            running = True
    p.terminate()  

basically just using the time module to allow a loop to run for five seconds and then moving on, this assumes timeout is given in seconds. Though I'd point out that if this was used with the code the OP originally posted, this would work, as print was in a second function separate from the loop and would be carried out immediately after calling this function.

Upvotes: 0

Alp
Alp

Reputation: 2826

Use a separate thread to start the process, wait 5 seconds, then terminate the process. Meanwhile the main thread can do the work you want to happen immediately:

from multiprocessing import Process
import time
import threading 

def f(name):
    time.sleep(100)
    print 'hello', name

def run_process_with_timeout(timeout, target, args):
    p = Process(target=target, args=args)
    p.start()
    time.sleep(timeout)
    p.terminate()

if __name__ == '__main__':
    t = threading.Thread(target=run_process_with_timeout, args=(5,f,('bob',)))
    t.start()
    print "This Needs to be Printed Immediately"

Upvotes: 1

astreal
astreal

Reputation: 3513

You might want to take a look at that SO thread.

basically their solution is to use the timeout capability of the threading module by running the process in a separate thread.

Upvotes: 1

hvb
hvb

Reputation: 2668

You are right, there is no such function in Python 2.x in the subprocess library. However, with Python 3.3 you can use:

p = subprocess.Popen(...)
try:
    p.wait(timeout=5)
except TimeoutError:
    p.kill()

With older Python versions, you would have to write a loop that calls p.poll() and checks the returncode, e.g. once per second.

This is (like polling in general) not optimal from performance point-of-view, but it always depends on what you expect.

Upvotes: 0

Related Questions