I'm calling a function in Python which I know may stall and force me to restart the script. How do I call the function or what do I wrap it in so that if it takes longer than 5 seconds the script cancels it and does something else.
Thanks
I'm calling a function in Python which I know may stall and force me to restart the script. How do I call the function or what do I wrap it in so that if it takes longer than 5 seconds the script cancels it and does something else.
Thanks
Maybe try to call it from other thread, which You could easily terminate.
What yabcok said - start a new thread to call the function. In the original thread, sleep for 5 seconds, then terminate the function thread if it hasn't already ended.
Maybe there is a better approach to your problem? Why might the function take longer than 5 seconds?
If this is some kind of network or file operation, you might also consider using nonblocking IO. This can be a better option if you're doing a lot of these types of operations at once (otherwise, you can bog your system down fairly quickly with a lot of threads). Here's a socket howto that covers nonblocking IO (in the context of network operations).
The downside? Well, it can be a pain to program. Sometimes even moreso than just using a thread.
I'm making some local xmlrpc calls with a timeout using the following code, borrowed from an ActiveState Cookbook recipe:
def timeout(func, args=(), kwargs={}, timeout_duration=10, default=None):
"""This function will spawn a thread and run the given function
using the args, kwargs and return the given default value if the
timeout_duration is exceeded.
"""
import threading
class InterruptableThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.result = default
def run(self):
self.result = func(*args, **kwargs)
it = InterruptableThread()
it.start()
it.join(timeout_duration)
if it.isAlive():
return it.result
else:
return it.result
Invoking it with a 5 second timeout:
result = timeout(remote_calculate, (myarg,), timeout_duration=5)
I would use the time() method from time to compare the time while you're running your function, but clearly this only works if you'd be hitting an infinite loop, not a function hanging.
def meth():
start_time = time()
while(whatever):
do_something
if time() - smart_time > 5:
return
But I'm just a small fry.
You may use the signal package
In [1]: import signal
# Register an handler for the timeout
In [2]: def handler(signum, frame):
...: print "Forever is over!"
...: raise Exception("end of time")
...:
# This function *may* run for an indetermined time...
In [3]: def loop_forever():
...: import time
...: while 1:
...: print "sec"
...: time.sleep(1)
...:
...:
# Register the signal function handler
In [4]: signal.signal(signal.SIGALRM, handler)
Out[4]: 0
# Define a timeout for your function
In [5]: signal.alarm(10)
Out[5]: 0
In [6]: try:
...: loop_forever()
...: except Exception, exc:
...: print exc
....:
sec
sec
sec
sec
sec
sec
sec
sec
Forever is over!
end of time
# Cancel the timer if the function returned before timeout
# (ok, mine won't but yours maybe will :)
In [7]: signal.alarm(0)
Out[7]: 0
10 seconds after the call alarm.alarm(10)
, the handler is called. This raises an exception that you can intercept from the regular Python code.
This module doesn't play well with threads (but then, who does?)