["python"]
Timeout function if it takes too long to finish

I have a shell script that loops through a text file containing URL:s that I want to visit and take screenshots of. All this is done and simple. The script initializes a class that when run creates a screenshot of each site in the list. Some sites take a very, very long time to load, and some might not be loaded at all. So I want to wrap the screengrabber-function in a timeout script, making the function return False if it couldn't finish within 10 seconds. I'm content with the simplest solution possible, maybe setting a asynchronous timer that will return False after 10 seconds no matter what actually happens inside the function?
The process for timing out an operations is described in the documentation for signal. The basic idea is to use signal handlers to set an alarm for some time interval and raise an exception once that timer expires. Note that this will only work on UNIX, and the timer duration must be an integer (and so it can not be < 1s). Here's an implementation that creates a decorator (save the following code as timeout.py). import errno import os import signal import functools class TimeoutError(Exception): pass def timeout(seconds=10, error_message=os.strerror(errno.ETIME)): def decorator(func): def _handle_timeout(signum, frame): raise TimeoutError(error_message) @functools.wraps(func) def wrapper(*args, **kwargs): signal.signal(signal.SIGALRM, _handle_timeout) signal.alarm(seconds) try: result = func(*args, **kwargs) finally: signal.alarm(0) return result return wrapper return decorator This creates a decorator called @timeout that can be applied to any long running functions. So, in your application code, you can use the decorator like so: from timeout import timeout # Timeout a long running function with the default expiry of 10 seconds. @timeout def long_running_function1(): ... # Timeout after 5 seconds @timeout(5) def long_running_function2(): ... # Timeout after 30 seconds, with the error "Connection timed out" @timeout(30, os.strerror(errno.ETIMEDOUT)) def long_running_function3(): ...