mirror of
https://github.com/jupyter/notebook.git
synced 2025-01-30 12:11:32 +08:00
Refactoring the notebook app to support the new config system.
This commit is contained in:
parent
52b29af5bd
commit
d04eb09f2e
@ -1,5 +1,9 @@
|
||||
"""A kernel manager for multiple kernels."""
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
import logging
|
||||
import signal
|
||||
import sys
|
||||
@ -11,6 +15,9 @@ from IPython.config.configurable import Configurable
|
||||
from IPython.zmq.ipkernel import launch_kernel
|
||||
from IPython.utils.traitlets import Instance, Dict, Unicode
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Classes
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
class DuplicateKernelError(Exception):
|
||||
pass
|
||||
|
@ -1,3 +1,9 @@
|
||||
"""A tornado based IPython notebook server."""
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
@ -14,22 +20,30 @@ from tornado import options
|
||||
from tornado import web
|
||||
|
||||
from kernelmanager import KernelManager
|
||||
from sessionmanager import SessionManager
|
||||
from handlers import (
|
||||
MainHandler, KernelHandler, KernelActionHandler, ZMQStreamHandler,
|
||||
NotebookRootHandler, NotebookHandler
|
||||
)
|
||||
from routers import IOPubStreamRouter, ShellStreamRouter
|
||||
|
||||
options.define("port", default=8888, help="run on the given port", type=int)
|
||||
from IPython.core.application import BaseIPythonApplication
|
||||
from IPython.zmq.session import Session
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Module globals
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
_kernel_id_regex = r"(?P<kernel_id>\w+-\w+-\w+-\w+-\w+)"
|
||||
_kernel_action_regex = r"(?P<action>restart|interrupt)"
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# The Tornado web application
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
class NotebookWebApplication(web.Application):
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, kernel_manager, log):
|
||||
handlers = [
|
||||
(r"/", MainHandler),
|
||||
(r"/kernels", KernelHandler),
|
||||
@ -45,9 +59,8 @@ class NotebookWebApplication(web.Application):
|
||||
)
|
||||
web.Application.__init__(self, handlers, **settings)
|
||||
|
||||
self.context = zmq.Context()
|
||||
self.kernel_manager = KernelManager(self.context)
|
||||
self._session_dict = {}
|
||||
self.kernel_manager = kernel_manager
|
||||
self.log = log
|
||||
self._routers = {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@ -59,14 +72,32 @@ class NotebookWebApplication(web.Application):
|
||||
return self.kernel_manager.kernel_ids
|
||||
|
||||
def start_kernel(self):
|
||||
# TODO: pass command line options to the kernel in start_kernel()
|
||||
kernel_id = self.kernel_manager.start_kernel()
|
||||
logging.info("Kernel started: %s" % kernel_id)
|
||||
self.start_session(kernel_id)
|
||||
self.log.info("Kernel started: %s" % kernel_id)
|
||||
self.start_session_manager(kernel_id)
|
||||
return kernel_id
|
||||
|
||||
def start_session_manager(self, kernel_id):
|
||||
sm = self.kernel_manager.create_session_manager(kernel_id)
|
||||
self._session_dict[kernel_id] = sm
|
||||
iopub_stream = sm.get_iopub_stream()
|
||||
shell_stream = sm.get_shell_stream()
|
||||
iopub_router = IOPubStreamRouter(iopub_stream)
|
||||
shell_router = ShellStreamRouter(shell_stream)
|
||||
self._routers[(kernel_id, 'iopub')] = iopub_router
|
||||
self._routers[(kernel_id, 'shell')] = shell_router
|
||||
self.log.debug("Session manager started for kernel: %s" % kernel_id)
|
||||
|
||||
def kill_kernel(self, kernel_id):
|
||||
sm = self._session_dict.pop(kernel_id)
|
||||
sm.stop()
|
||||
self.kernel_manager.kill_kernel(kernel_id)
|
||||
self.log.info("Kernel killed: %s" % kernel_id)
|
||||
|
||||
def interrupt_kernel(self, kernel_id):
|
||||
self.kernel_manager.interrupt_kernel(kernel_id)
|
||||
logging.info("Kernel interrupted: %s" % kernel_id)
|
||||
self.log.debug("Kernel interrupted: %s" % kernel_id)
|
||||
|
||||
def restart_kernel(self, kernel_id):
|
||||
# Create the new kernel first so we can move the clients over.
|
||||
@ -84,48 +115,106 @@ class NotebookWebApplication(web.Application):
|
||||
# TODO: This causes a hard crash in ZMQStream.close, which sets
|
||||
# self.socket to None to hastily. We will need to fix this in PyZMQ
|
||||
# itself. For now, we just leave the old kernel running :(
|
||||
# sm = self.kernel_manager.get_session_manager(kernel_id)
|
||||
# session_id = self._session_dict[kernel_id]
|
||||
# sm.stop_session(session_id)
|
||||
# self.kernel_manager.kill_kernel(kernel_id)
|
||||
# self.kill_kernel(kernel_id)
|
||||
|
||||
logging.info("Kernel restarted")
|
||||
self.log.debug("Kernel restarted: %s -> %s" % (kernel_id, new_kernel_id))
|
||||
return new_kernel_id
|
||||
|
||||
def start_session(self, kernel_id):
|
||||
sm = self.kernel_manager.get_session_manager(kernel_id)
|
||||
session_id = sm.start_session()
|
||||
self._session_dict[kernel_id] = session_id
|
||||
iopub_stream = sm.get_iopub_stream(session_id)
|
||||
shell_stream = sm.get_shell_stream(session_id)
|
||||
iopub_router = IOPubStreamRouter(iopub_stream)
|
||||
shell_router = ShellStreamRouter(shell_stream)
|
||||
self._routers[(kernel_id, session_id, 'iopub')] = iopub_router
|
||||
self._routers[(kernel_id, session_id, 'shell')] = shell_router
|
||||
logging.info("Session started: %s, %s" % (kernel_id, session_id))
|
||||
|
||||
def stop_session(self, kernel_id):
|
||||
# TODO: finish this!
|
||||
sm = self.kernel_manager.get_session_manager(kernel_id)
|
||||
session_id = self._session_dict[kernel_id]
|
||||
|
||||
def get_router(self, kernel_id, stream_name):
|
||||
session_id = self._session_dict[kernel_id]
|
||||
router = self._routers[(kernel_id, session_id, stream_name)]
|
||||
router = self._routers[(kernel_id, stream_name)]
|
||||
return router
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Aliases and Flags
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
flags = dict(ipkernel_flags)
|
||||
|
||||
# the flags that are specific to the frontend
|
||||
# these must be scrubbed before being passed to the kernel,
|
||||
# or it will raise an error on unrecognized flags
|
||||
notebook_flags = []
|
||||
|
||||
aliases = dict(ipkernel_aliases)
|
||||
|
||||
aliases.update(dict(
|
||||
ip = 'IPythonNotebookApp.ip',
|
||||
port = 'IPythonNotebookApp.port'
|
||||
colors = 'ZMQInteractiveShell.colors',
|
||||
editor = 'IPythonWidget.editor',
|
||||
))
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# IPythonNotebookApp
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
class IPythonNotebookApp(BaseIPythonApplication):
|
||||
name = 'ipython-notebook'
|
||||
default_config_file_name='ipython_notebook_config.py'
|
||||
|
||||
description = """
|
||||
The IPython HTML Notebook.
|
||||
|
||||
This launches a Tornado based HTML Notebook Server that serves up an
|
||||
HTML5/Javascript Notebook client.
|
||||
"""
|
||||
|
||||
classes = [IPKernelApp, ZMQInteractiveShell, ProfileDir, Session,
|
||||
KernelManager, SessionManager]
|
||||
flags = Dict(flags)
|
||||
aliases = Dict(aliases)
|
||||
|
||||
kernel_argv = List(Unicode)
|
||||
|
||||
# connection info:
|
||||
ip = Unicode(LOCALHOST, config=True,
|
||||
help="The IP address the notebook server will listen on."
|
||||
)
|
||||
|
||||
port = Int(8888, config=True,
|
||||
help="The port the notebook server will listen on."
|
||||
)
|
||||
|
||||
# the factory for creating a widget
|
||||
widget_factory = Any(RichIPythonWidget)
|
||||
|
||||
def parse_command_line(self, argv=None):
|
||||
super(IPythonNotebookApp, self).parse_command_line(argv)
|
||||
if argv is None:
|
||||
argv = sys.argv[1:]
|
||||
|
||||
self.kernel_argv = list(argv) # copy
|
||||
# kernel should inherit default config file from frontend
|
||||
self.kernel_argv.append("KernelApp.parent_appname='%s'"%self.name)
|
||||
# scrub frontend-specific flags
|
||||
for a in argv:
|
||||
if a.startswith('--') and a[2:] in qt_flags:
|
||||
self.kernel_argv.remove(a)
|
||||
|
||||
def init_kernel_manager(self):
|
||||
# Don't let Qt or ZMQ swallow KeyboardInterupts.
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
|
||||
# Create a KernelManager and start a kernel.
|
||||
self.kernel_manager = KernelManager(config=self.config, log=self.log)
|
||||
|
||||
def initialize(self, argv=None):
|
||||
super(IPythonNotebookApp, self).initialize(argv)
|
||||
self.init_kernel_mananger()
|
||||
self.web_app = NotebookWebApplication()
|
||||
self.http_server = httpserver.HTTPServer(self.web_app)
|
||||
self.http_server.listen(self.port)
|
||||
|
||||
def start(self):
|
||||
self.log.info("The IPython Notebook is running at: http://%s:%i" % (self.ip, self.port))
|
||||
ioloop.IOLoop.instance().start()
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Main entry point
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def launch_new_instance():
|
||||
options.parse_command_line()
|
||||
application = NotebookWebApplication()
|
||||
http_server = httpserver.HTTPServer(application)
|
||||
http_server.listen(options.options.port)
|
||||
print "IPython Notebook running at: http://127.0.0.1:8888"
|
||||
print "The github master of tornado is required to run this server:"
|
||||
print " https://github.com/facebook/tornado/tree/master/tornado"
|
||||
ioloop.IOLoop.instance().start()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
app = IPythonNotebookApp()
|
||||
app.initialize()
|
||||
app.start()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user