75

I would like to call foo(n) but stop it if it runs for more than 10 seconds. What's a good way to do this?

I can see that I could in theory modify foo itself to periodically check how long it has been running for but I would prefer not to do that.

6
  • 2
    What do you have inside foo? Is it a loop? Are you going to run foo as a different thread? Commented Feb 17, 2013 at 11:05
  • I would really consider modifying foo, but otherwise see this question: stackoverflow.com/questions/492519/… or this one: stackoverflow.com/questions/4158502/… Commented Feb 17, 2013 at 11:06
  • @ATOzTOA It's a complicated piece of code doing a complicated calculation. I didn't write that code. Commented Feb 17, 2013 at 11:06
  • @felipa So, do you run it in a different thread? Commented Feb 17, 2013 at 11:07
  • @ATOzTOA Currently there are no threads. Your link looks very promising however. Commented Feb 17, 2013 at 11:08

2 Answers 2

82

Here you go:

import multiprocessing import time # Your foo function def foo(n): for i in range(10000 * n): print "Tick" time.sleep(1) if __name__ == '__main__': # Start foo as a process p = multiprocessing.Process(target=foo, name="Foo", args=(10,)) p.start() # Wait 10 seconds for foo time.sleep(10) # Terminate foo p.terminate() # Cleanup p.join() 

This will wait 10 seconds for foo and then kill it.

Update

Terminate the process only if it is running.

# If thread is active if p.is_alive(): print "foo is running... let's kill it..." # Terminate foo p.terminate() 

Update 2 : Recommended

Use join with timeout. If foo finishes before timeout, then main can continue.

# Wait a maximum of 10 seconds for foo # Usage: join([timeout in seconds]) p.join(10) # If thread is active if p.is_alive(): print "foo is running... let's kill it..." # Terminate foo p.terminate() p.join() 
Sign up to request clarification or add additional context in comments.

11 Comments

Thanks! I would ideally like to only kill the process if it hasn't terminated already. Is there way to check for this?
Thanks very much (although timeout doesn't appear in your answer). This is very helpful and informative. If anyone ever upvotes this question (the linked questions don't have such useful answers it seems) then I will upvote you of course. I can't currently it seems.
Come on, using a signal is faster, and doesn't rely on a low level fork().
@Goldname It doesn't really matter. It is a safe construct I normally use. You don't want the thread to run on import.
How we return the value from foo?
|
16
import signal #Sets an handler function, you can comment it if you don't need it. signal.signal(signal.SIGALRM,handler_function) #Sets an alarm in 10 seconds #If uncaught will terminate your process. signal.alarm(10) 

The timeout is not very precise, but can do if you don't need extreme precision.

Another way is to use the resource module, and set the maximum CPU time.

7 Comments

What you be able to expand this a little to show how it terminates the function foo and not the whole python script for example? I want my script to carry on, just for the call to foo to timeout after 10 seconds.
Write a function handler to do that, for example in every iteration in the function check for a global variable, and change that variable in the signal handler.
@LtWorf OP already said the function is a complex one and not a single loop. So, this won't work.
I have to see a complex function that doesn't use loops or recursion.
just a heads up, signal only works in main thread , so for people using multiple threads it probably isn't a good idea to use signal module
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.