Adding cell timeouts to IPython.
Let's say you want to add a timeout to cells, so that cells that run for too long get interrupted.
A handy way to do this is with signal.alarm.
import signal
import time
class TookTooLong(Exception):
"""A special error to raise when a cell takes too long"""
def __str__(self):
return "The cell took too long to execute"
def raise_on_alarm(*args):
"""signal handler to raise our special error"""
raise TookTooLong()
# register our handler when the alarm signal fires:
signal.signal(signal.SIGALRM, raise_on_alarm)
# start the alarm timer:
signal.alarm(1)
# and run some code that will take too long:
time.sleep(2)
--------------------------------------------------------------------------- TookTooLong Traceback (most recent call last) <ipython-input-1-3383c83af88d> in <module> 19 signal.alarm(1) 20 # and run some code that will take too long: ---> 21 time.sleep(2) <ipython-input-1-3383c83af88d> in raise_on_alarm(*args) 11 def raise_on_alarm(*args): 12 """signal handler to raise our special error""" ---> 13 raise TookTooLong() 14 15 TookTooLong: The cell took too long to execute
We can register starting the timer before each cell and clearing it after it's done with IPython events:
ip = get_ipython()
# start the alarm when the cell starts
ip.events.register('pre_run_cell', lambda : signal.alarm(1))
# cancel the alarm when it finishes
ip.events.register('post_run_cell', lambda : signal.alarm(0))
This one is fine because it takes less than a second:
time.sleep(0.5)
But two seconds is too long!
time.sleep(2)
--------------------------------------------------------------------------- TookTooLong Traceback (most recent call last) <ipython-input-4-e0dd5f34ad7e> in <module> ----> 1 time.sleep(2) <ipython-input-1-3383c83af88d> in raise_on_alarm(*args) 11 def raise_on_alarm(*args): 12 """signal handler to raise our special error""" ---> 13 raise TookTooLong() 14 15 TookTooLong: The cell took too long to execute
You can enable this by default by putting it in an IPython extension.