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?)