Normalerweise würde ich lieber einen Kontextmanager verwenden, wie von @ josh-lee vorgeschlagen
Falls jedoch jemand daran interessiert ist, dies als Dekorateur zu implementieren, ist hier eine Alternative.
So würde es aussehen:
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')
Und das ist das timeout.pyModul:
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
Die Ausgabe:
python
rocks
A Done
timing
Traceback (most recent call last):
...
timeout.TimeoutError: execution expired
out
Beachten Sie, dass TimeoutErrordie dekorierte Methode auch dann in einem anderen Thread ausgeführt wird , wenn sie ausgelöst wird. Wenn Sie auch möchten, dass dieser Thread "gestoppt" wird, lesen Sie: Gibt es eine Möglichkeit, einen Thread in Python zu beenden?