diff --git a/IPython/kernel/kernelrestarter.py b/IPython/kernel/kernelrestarter.py new file mode 100644 index 0000000..66c377c --- /dev/null +++ b/IPython/kernel/kernelrestarter.py @@ -0,0 +1,62 @@ +"""A basic in process kernel monitor with autorestarting. + +This watches a kernel's state using KernelManager.is_alive and auto +restarts the kernel if it dies. +""" + +#----------------------------------------------------------------------------- +# Copyright (C) 2013 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +import zmq +from zmq.eventloop import ioloop + + +from IPython.config.configurable import LoggingConfigurable +from IPython.utils.traitlets import ( + Instance, Float +) + +#----------------------------------------------------------------------------- +# Code +#----------------------------------------------------------------------------- + +class KernelRestarter(LoggingConfigurable): + """Monitor and autorestart a kernel.""" + + loop = Instance('zmq.eventloop.ioloop.IOLoop', allow_none=False) + def _loop_default(self): + return ioloop.IOLoop.instance() + + kernel_manager = Instance('IPython.kernel.kernelmanager.KernelManager') + + time_to_dead = Float(3.0, config=True, + help="""Kernel heartbeat interval in seconds.""" + ) + + def __init__(self, **kwargs): + super(KernelRestarter, self).__init__(**kwargs) + + def start(self): + self.pc = ioloop.PeriodicCallback(self.poll, self.time_to_dead, self.ioloop) + self.pc.start() + + def poll(self): + if not self.kernel_manager.is_alive(): + self.stop() + # This restart event should leave the connection file in place so + # the ports are the same. Because this takes place below the + # MappingKernelManager, the kernel_id will also remain the same. + self.kernel_manager.restart_kernel(now=True); + self.start() + + def stop(self): + self.pc.stop() + self.pc = None