I usually prefer to use the context manager as suggested by @ josh-lee
But if someone is interested in having this implemented as a decorator, here is an alternative.
Here's how it would look:
import time from timeout import timeout class Test(object): @timeout(2) def test_a(self, foo, bar): print foo time.sleep(1) print bar return 'A Done' @timeout(2) def test_b(self, foo, bar): print foo time.sleep(3) print bar return 'B Done' t = Test() print t.test_a('python', 'rocks') print t.test_b('timing', 'out')
And this is the timeout.py module:
import threading class TimeoutError(Exception): pass class InterruptableThread(threading.Thread): def __init__(self, func, *args, **kwargs): threading.Thread.__init__(self) self._func = func self._args = args self._kwargs = kwargs self._result = None def run(self): self._result = self._func(*self._args, **self._kwargs) @property def result(self): return self._result class timeout(object): def __init__(self, sec): self._sec = sec def __call__(self, f): def wrapped_f(*args, **kwargs): it = InterruptableThread(f, *args, **kwargs) it.start() it.join(self._sec) if not it.is_alive(): return it.result raise TimeoutError('execution expired') return wrapped_f
Exit:
python rocks A Done timing Traceback (most recent call last): ... timeout.TimeoutError: execution expired out
Please note that even if TimeoutError selected, the decorated method will continue to work in another thread. If you also want this thread to be “stopped”, see: Is there a way to kill a thread in Python?
Seba Jan 27 '16 at 13:38 on 2016-01-27 13:38
source share