Skip to content

Instantly share code, notes, and snippets.

@nvie
Created February 22, 2012 20:09
Show Gist options
  • Save nvie/1886939 to your computer and use it in GitHub Desktop.
Save nvie/1886939 to your computer and use it in GitHub Desktop.
Example of a time-guarded context
import signal
class JobTimeoutException(Exception):
pass
class death_pentalty_after(object):
def __init__(self, timeout):
self._timeout = timeout
def __enter__(self):
self.setup_death_penalty()
def __exit__(self, type, value, traceback):
# Always cancel immediately, since we're done
try:
self.cancel_death_penalty()
except JobTimeoutException:
# Weird case: we're done with the with body, but now the alarm is
# fired. We may safely ignore this situation and consider the
# body done.
pass
# __exit__ may return True to supress further exception handling. We
# don't want to suppress any exceptions here, since all errors should
# just pass through, JobTimeoutException being handled normally to the
# invoking context.
return False
def handle_death_penalty(self, signum, frame):
raise JobTimeoutException('Job exceeded maximum timeout '
'value (%d seconds).' % self._timeout)
def setup_death_penalty(self):
"""Sets up an alarm signal and a signal handler that raises
a JobTimeoutException after the timeout amount (expressed in
seconds).
"""
signal.signal(signal.SIGALRM, self.handle_death_penalty)
signal.alarm(self._timeout)
def cancel_death_penalty(self):
"""Removes the death penalty alarm and puts back the system into
default signal handling.
"""
signal.alarm(0)
signal.signal(signal.SIGALRM, signal.SIG_DFL)
if __name__ == '__main__':
def slow_fib(n):
if n <= 1:
return 1
return slow_fib(n - 2) + slow_fib(n - 1)
try:
with death_pentalty_after(8):
for i in range(0, 50):
print i, '=>', slow_fib(i)
except JobTimeoutException:
print('Buy a faster machine to calculate more fibonacci numbers :)')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment