jupyter notebook的通信

提示用户输入一段代码,当用户输入以后执行。这种模式经常被称为REPL(交互式开发环境),或者Read-Eval-Print-Loop(读取﹣求值﹣输出循环).jupyter notebook就是这样一种在web端的交互式开发环境,如下:


jupyter notebook示例

对应.ipynb文件的内容:

{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pi is rough3.142608\n"
     ]
    }
   ],
   "source": [
    "import scala.math.random\n",
    "import org.apache.spark._\n",
    "val slices = 10\n",
    "val n = math.min(100000L * slices, Int.MaxValue).toInt\n",
    "val count = sc.parallelize(1 until n, slices).map{ i =>\n",
    "                                                val x = random*2 - 1\n",
    "                                                val y = random*2 -1\n",
    "                                                if (x*x + y*y <1) 1 else 0\n",
    "                                                }.reduce(_+_)\n",
    "println(\"pi is rough\" + 4.0*count/n)"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Apache Toree - Scala",
   "language": "scala",
   "name": "apache_toree_scala"
  },
  "language_info": {
   "name": "scala",
   "version": "2.11.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}

IPython 内核 所有其它接口,包括Notebook,Qt控制台,ipython控制台和其它第三方接口,都使用IPython内核。IPython内核是一个独立的进程,负责执行用户代码和其它事情,例如计算可能的补全。前端处理器,例如notebook和Qt控制台,使用ZeroMQ传输JSON消息与IPython内核通信,前端处理器与IPython内核通信使用的协议详细描述请参考Jupyter 消息

notebook简单通信图

Notebook 前端处理器做一些额外的事情。除了运行你的代码,它还储存代码和输出、以及markdown注释在一个可编辑的文档中,我们称这个文档为一个notebook。当你保存这个文档时,它会从你的浏览器发送到notebook服务器,服务器将文档保存为.ipynb为拓展名的JSON格式文件,notebook服务器而不是内核,负责保存和载入notebook,因此你可以编辑notebook即使你没有那种编程语言的内核,你仅仅不能运行notebook中的代码。内核不知道notebook文档任何事情,它只是在用户运行代码时获取用户发送的代码并执行。导出notebooks到其他格式 Jupyter中的工具Nbconvert可以将notebook文件转换到其它格式,例如HTML,LaTex.
使用nbconvert和HTML导出器。当你输入一个网址,它从输入的网址获取notebook,然后将其转换为HTML格式,并将HTML呈现给你。

jupyter

Python Notebook中输入的代码经由浏览器发送给Web服务器,再由Web服务器发送消息到IPython的Kernel执行代码,在Kernel中执行代码所产生的输出会再发送给Web服务器从而发送给浏览器,完成整个运行过程。Web服务器和Kernel之间采用ZeroMQ进行通信。下面为其通信的示意图:
通信示意图

图中,Kernel经由绿色的DEAL-ROUTER通道接收来自Web服务器的命令消息,并返回应答消息。通过红色的PUB-SUB通道传输被执行代码所产生的输出信息。
在Kernel中,用户代码在一个用户环境(字典)中执行,通常无法获得关于Kernel的信息。但是由于用户代码和Kernel在同一进程中执行,因此我们可以通过一些特殊的代码研究Kernel是如何接收、运行并返回消息的。
两种思路:
一、从websocket入手
打开一个新的notebook: http://127.0.0.1:5000/notebooks/Untitled1.ipynb
从chrome调试面板的Network可以看到,有个websocket:ws://127.0.0.1:5000/api/kernels/d13a50b0-6baa-4d5e-8564-95f224daxxxx/channels?session_id=F552491A7C0448A2B5567DE1A71Cxxxx,代码经由它往后端发送,也经由它接收后台返回的信息
当我们运行上头的print("hello world")时,往后台发送如下数据

{
"header":
{
"msg_id":"D8FA79DCD7D140DF8F9C37EE15D9FD6D",
"username":"username",
"session":"91608A811CAE4FA6A5E09D37AF68DF32",
"msg_type":"execute_request",
"version":"5.0"
},
"metadata":{},
"content":
{
"code":"print(\"hello world\")",
"silent":false,
"store_history":true,
"user_expressions":{},
"allow_stdin":true,
"stop_on_error":true
},
"buffers":[],
"parent_header":{},
"channel":"shell"
}

接下来有5个frames:

{
"parent_header": 
{
"username": "username",
 "session": "91608A811CAE4FA6A5E09D37AF68DF32", 
"version": "5.0",
 "msg_id": "D8FA79DCD7D140DF8F9C37EE15D9FD6D",
 "msg_type": "execute_request"
}, 
"msg_type": "status",
 "msg_id": "ce11828e-1c2a-4254-962f-2db9e2ff3353", 
"content": 
{
"execution_state": "busy"
}, 
"header": 
{
"username": "root",
 "version": "5.0", 
"msg_type": "status",
 "msg_id": "ce11828e-1c2a-4254-962f-2db9e2ff3353", 
"session": "604a11a4-14eb-4f8a-b32d-044d4c195bf3",
 "date": "2017-12-03T20:05:06.816757"
}, 
"channel": "iopub",
 "buffers": [], 
"metadata": 
{
"timestamp": "1512302706811"
}
}
{
"parent_header":
 {
"username": "username", 
"session": "91608A811CAE4FA6A5E09D37AF68DF32", 
"version": "5.0",
 "msg_id": "D8FA79DCD7D140DF8F9C37EE15D9FD6D",
 "msg_type": "execute_request"
}, 
"msg_type": "execute_input",
 "msg_id": "116696e7-befa-40c7-98c1-88e32e1e9b63",
 "content": 
{
"execution_count": 1, 
"code": "print(\"hello world\")"
}, 
"header":
 {
"username": "root",
 "version": "5.0",
 "msg_type": "execute_input",
 "msg_id": "116696e7-befa-40c7-98c1-88e32e1e9b63", 
"session": "604a11a4-14eb-4f8a-b32d-044d4c195bf3", 
"date": "2017-12-03T20:05:06.829865"
}, 
"channel": "iopub", 
"buffers": [],
 "metadata": 
{
"timestamp": "1512302706826"
}
}
{
"parent_header": 
{
"username": "username",
 "session": "91608A811CAE4FA6A5E09D37AF68DF32", 
"version": "5.0", "msg_id": "D8FA79DCD7D140DF8F9C37EE15D9FD6D", 
"msg_type": "execute_request"
}, 
"msg_type": "stream",
 "msg_id": "d3c9ffa1-108f-4ea2-88db-100985fe23d0",
 "content": 
{
"text": "hello world", "name": "stdout"
}, 
"header": 
{
"username": "root", 
"version": "5.0", 
"msg_type": "stream",
 "msg_id": "d3c9ffa1-108f-4ea2-88db-100985fe23d0",
 "session": "604a11a4-14eb-4f8a-b32d-044d4c195bf3", 
"date": "2017-12-03T20:05:07.071811"
}, 
"channel": "iopub",
 "buffers": [],
 "metadata": 
{
"timestamp": "1512302707065"
}
}
{
"parent_header":
 {
"username": "username", 
"session": "91608A811CAE4FA6A5E09D37AF68DF32",
 "version": "5.0", 
"msg_id": "D8FA79DCD7D140DF8F9C37EE15D9FD6D",
 "msg_type": "execute_request"
},
 "msg_type": "execute_reply",
 "msg_id": "6ee99d0d-9c92-41ce-be06-39241719f321",
 "content": 
{
"status": "ok", 
"execution_count": 1, 
"payload": [],
 "user_expressions": {}
}, 
"header":
 {
"username": "root",
 "version": "5.0",
 "msg_type": "execute_reply",
 "msg_id": "6ee99d0d-9c92-41ce-be06-39241719f321",
 "session": "604a11a4-14eb-4f8a-b32d-044d4c195bf3",
 "date": "2017-12-03T20:05:07.097685"
}, 
"channel": "shell",
 "buffers": [], 
"metadata": 
{
"timestamp": "1512302707094"
}
}
{
"parent_header": 
{
"username": "username",
 "session": "91608A811CAE4FA6A5E09D37AF68DF32",
 "version": "5.0",
 "msg_id": "D8FA79DCD7D140DF8F9C37EE15D9FD6D", 
"msg_type": "execute_request"
}, 
"msg_type": "status",
 "msg_id": "32857f80-db87-4775-9350-fe009a8e9c18",
 "content": {
"execution_state": "idle"
}, 
"header":
 {
"username": "root", 
"version": "5.0", 
"msg_type": "status",
 "msg_id": "32857f80-db87-4775-9350-fe009a8e9c18",
 "session": "604a11a4-14eb-4f8a-b32d-044d4c195bf3", 
"date": "2017-12-03T20:05:07.098384"
},
 "channel": "iopub",
 "buffers": [], 
"metadata": 
{
"timestamp": "1512302707095"
}
}
chrome/Network/WS/Frames

在支持WebSocket的浏览器中,在创建socket之后。可以通过onopen,onmessage,onclose和onerror四个事件实现对socket进行响应

一个简单的 示例

var ws = new WebSocket(“ws://localhost:8080”);

ws.onopen = function()

{  console.log(“open”);

  ws.send(“hello”);

};

ws.onmessage = function(evt)

{

  console.log(evt.data)

};

ws.onclose = function(evt)

{

  console.log(“WebSocketClosed!”);

};

ws.onerror = function(evt)

{

  console.log(“WebSocketError!”);

};

1.var ws = new WebSocket(“ws://localhost:8080”);

申请一个WebSocket对象,参数是需要连接的服务器端的地址,同http协议使用http://开头一样,WebSocket协议的URL使用ws://开头,另外安全的WebSocket协议使用wss://开头。

ws.send(“hello”);
用于将消息发送到服务端
2.ws.onopen = function() { console.log(“open”)};

当websocket创建成功时,即会触发onopen事件
3.ws.onmessage = function(evt) { console.log(evt.data) };
当客户端收到服务端发来的消息时,会触发onmessage事件,参数evt.data中包含server传输过来的数据
4.ws.onclose = function(evt) { console.log(“WebSocketClosed!”); };

当客户端收到服务端发送的关闭连接的请求时,触发onclose事件
5.ws.onerror = function(evt) { console.log(“WebSocketError!”); };
如果出现连接,处理,接收,发送数据失败的时候就会触发onerror事件
我们可以看出所有的操作都是采用事件的方式触发的,这样就不会阻塞UI,使得UI有更快的响应时间,得到更好的用户体验。
二、从页面入手
在stack overflow里找到解答:

var handle_output = function (data) {console.log(data);}
//callbacks.iopub.output is used to get the data from execute
var callbacks = {
            iopub : {output : handle_output,}
}
//(read the source F12->static/notebook/js/services/kernels/kernel.js)
//kernel.js/717th lines Kernel.prototype.execute
var kernel = IPython.notebook.kernel;
kernel.execute("print('hello')",callbacks)

kernel.js的function:

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
define('services/kernels/kernel',[
    'jquery',
    'base/js/utils',
    './comm',
    './serialize',
    'base/js/events'
], function($, utils, comm, serialize, events) {
    "use strict";

    /**
     * A Kernel class to communicate with the Python kernel. This
     * should generally not be constructed directly, but be created
     * by.  the `Session` object. Once created, this object should be
     * used to communicate with the kernel.
     * 
     * Preliminary documentation for the REST API is at
     * https://github.com/ipython/ipython/wiki/IPEP-16%3A-Notebook-multi-directory-dashboard-and-URL-mapping#kernels-api
     * 
     * @class Kernel
     * @param {string} kernel_service_url - the URL to access the kernel REST api
     * @param {string} ws_url - the websockets URL
     * @param {string} name - the kernel type (e.g. python3)
     */
    var Kernel = function (kernel_service_url, ws_url, name) {
        this.events = events;

        this.id = null;
        this.name = name;
        this.ws = null;

        this.kernel_service_url = kernel_service_url;
        this.kernel_url = null;
        this.ws_url = ws_url || utils.get_body_data("wsUrl");
        if (!this.ws_url) {
            // trailing 's' in https will become wss for secure web sockets
            this.ws_url = location.protocol.replace('http', 'ws') + "//" + location.host;
        }

        this.username = "username";
        this.session_id = utils.uuid();
        this._msg_callbacks = {};
        this._msg_queue = Promise.resolve();
        this.info_reply = {}; // kernel_info_reply stored here after starting

        if (typeof(WebSocket) !== 'undefined') {
            this.WebSocket = WebSocket;
        } else if (typeof(MozWebSocket) !== 'undefined') {
            this.WebSocket = MozWebSocket;
        } else {
            alert('Your browser does not have WebSocket support, please try Chrome, Safari or Firefox ≥ 6. Firefox 4 and 5 are also supported by you have to enable WebSockets in about:config.');
        }
        
        this.bind_events();
        this.init_iopub_handlers();
        this.comm_manager = new comm.CommManager(this);
        
        this.last_msg_id = null;
        this.last_msg_callbacks = {};

        this._autorestart_attempt = 0;
        this._reconnect_attempt = 0;
        this.reconnect_limit = 7;
        
        this._pending_messages = [];
    };

    /**
     * @function _get_msg
     */
    Kernel.prototype._get_msg = function (msg_type, content, metadata, buffers) {

        return msg;
    };

    /**
     * @function bind_events
     */
    Kernel.prototype.bind_events = function () {
       
    };

    /**
     * Initialize the iopub handlers.
     *
     * @function init_iopub_handlers
     */
    Kernel.prototype.init_iopub_handlers = function () {
      
    };

    /**
     * GET /api/kernels
     *
     * Get the list of running kernels.
     *
     * @function list
     * @param {function} [success] - function executed on ajax success
     * @param {function} [error] - functon executed on ajax error
     */
    Kernel.prototype.list = function (success, error) {
    
    };

    /**
     * POST /api/kernels
     *
     * Start a new kernel.
     *
     * In general this shouldn't be used -- the kernel should be
     * started through the session API. If you use this function and
     * are also using the session API then your session and kernel
     * WILL be out of sync!
     *
     * @function start
     * @param {params} [Object] - parameters to include in the query string
     * @param {function} [success] - function executed on ajax success
     * @param {function} [error] - functon executed on ajax error
     */
    Kernel.prototype.start = function (params, success, error) {
        return url;
    };

    /**
     * GET /api/kernels/[:kernel_id]
     *
     * Get information about the kernel.
     *
     * @function get_info
     * @param {function} [success] - function executed on ajax success
     * @param {function} [error] - functon executed on ajax error
     */
    Kernel.prototype.get_info = function (success, error) {
    };

    /**
     * DELETE /api/kernels/[:kernel_id]
     *
     * Shutdown the kernel.
     *
     * If you are also using sessions, then this function shoul NOT be
     * used. Instead, use Session.delete. Otherwise, the session and
     * kernel WILL be out of sync.
     *
     * @function kill
     * @param {function} [success] - function executed on ajax success
     * @param {function} [error] - functon executed on ajax error
     */
    Kernel.prototype.kill = function (success, error) {

    };

    /**
     * POST /api/kernels/[:kernel_id]/interrupt
     *
     * Interrupt the kernel.
     *
     * @function interrupt
     * @param {function} [success] - function executed on ajax success
     * @param {function} [error] - functon executed on ajax error
     */
    Kernel.prototype.interrupt = function (success, error) {

    };

    Kernel.prototype.restart = function (success, error) {
        /**
         * POST /api/kernels/[:kernel_id]/restart
         *
         * Restart the kernel.
         *
         * @function interrupt
         * @param {function} [success] - function executed on ajax success
         * @param {function} [error] - functon executed on ajax error
         */

    };

    Kernel.prototype.reconnect = function () {

    };

    Kernel.prototype._on_success = function (success) {
        /**
         * Handle a successful AJAX request by updating the kernel id and
         * name from the response, and then optionally calling a provided
         * callback.
         *
         * @function _on_success
         * @param {function} success - callback
         */

    };

    Kernel.prototype._on_error = function (error) {
        /**
         * Handle a failed AJAX request by logging the error message, and
         * then optionally calling a provided callback.
         *
         * @function _on_error
         * @param {function} error - callback
         */

    };

    Kernel.prototype._kernel_created = function (data) {
        /**
         * Perform necessary tasks once the kernel has been started,
         * including actually connecting to the kernel.
         *
         * @function _kernel_created
         * @param {Object} data - information about the kernel including id
         */

    };

    Kernel.prototype._kernel_connected = function () {
        /**
         * Perform necessary tasks once the connection to the kernel has
         * been established. This includes requesting information about
         * the kernel.
         *
         * @function _kernel_connected
         */

    };

    Kernel.prototype._kernel_dead = function () {
        /**
         * Perform necessary tasks after the kernel has died. This closing
         * communication channels to the kernel if they are still somehow
         * open.
         *
         * @function _kernel_dead
         */

    };

    Kernel.prototype.start_channels = function () {
        /**
         * Start the websocket channels.
         * Will stop and restart them if they already exist.
         *
         * @function start_channels
         */
    };

    Kernel.prototype._ws_opened = function (evt) {
        /**
         * Handle a websocket entering the open state,
         * signaling that the kernel is connected when websocket is open.
         *
         * @function _ws_opened
         */

    };

    Kernel.prototype._ws_closed = function(ws_url, error) {
        /**
         * Handle a websocket entering the closed state.  If the websocket
         * was not closed due to an error, try to reconnect to the kernel.
         *
         * @function _ws_closed
         * @param {string} ws_url - the websocket url
         * @param {bool} error - whether the connection was closed due to an error
         */

    };
    
    Kernel.prototype._schedule_reconnect = function () {
        /**
         * function to call when kernel connection is lost
         * schedules reconnect, or fires 'connection_dead' if reconnect limit is hit
         */

    };
    
    Kernel.prototype.stop_channels = function () {
        /**
         * Close the websocket. After successful close, the value
         * in `this.ws` will be null.
         *
         * @function stop_channels
         */

    };

    Kernel.prototype.is_connected = function () {
        /**
         * Check whether there is a connection to the kernel. This
         * function only returns true if websocket has been
         * created and has a state of WebSocket.OPEN.
         *
         * @function is_connected
         * @returns {bool} - whether there is a connection
         */
        // if any channel is not ready, then we're not connected

    };

    Kernel.prototype.is_fully_disconnected = function () {
        /**
         * Check whether the connection to the kernel has been completely
         * severed. This function only returns true if all channel objects
         * are null.
         *
         * @function is_fully_disconnected
         * @returns {bool} - whether the kernel is fully disconnected
         */
        return (this.ws === null);
    };
    
    Kernel.prototype._send = function(msg) {
      /**
       * Send a message (if the kernel is connected) or queue the message for future delivery
       *
       * Pending messages will automatically be sent when a kernel becomes connected.
       *
       * @function _send
       * @param msg
       */

    }
    
    Kernel.prototype.send_shell_message = function (msg_type, content, callbacks, metadata, buffers) {
        /**
         * Send a message on the Kernel's shell channel
         *
         * If the kernel is not connected, the message will be buffered.
         * 
         * @function send_shell_message
         */
        return msg.header.msg_id;
    };

    Kernel.prototype.kernel_info = function (callback) {
        /**
         * Get kernel info
         *
         * @function kernel_info
         * @param callback {function}
         *
         * When calling this method, pass a callback function that expects one argument.
         * The callback will be passed the complete `kernel_info_reply` message documented
         * [here](https://jupyter-client.readthedocs.io/en/latest/messaging.html#kernel-info)
         */
    };

    Kernel.prototype.comm_info = function (target_name, callback) {
        /**
         * Get comm info
         *
         * @function comm_info
         * @param callback {function}
         *
         * When calling this method, pass a callback function that expects one argument.
         * The callback will be passed the complete `comm_info_reply` message documented
         * [here](https://jupyter-client.readthedocs.io/en/latest/messaging.html#comm_info)
         */

    };

    Kernel.prototype.inspect = function (code, cursor_pos, callback) {
        /**
         * Get info on an object
         *
         * When calling this method, pass a callback function that expects one argument.
         * The callback will be passed the complete `inspect_reply` message documented
         * [here](https://jupyter-client.readthedocs.io/en/latest/messaging.html#object-information)
         *
         * @function inspect
         * @param code {string}
         * @param cursor_pos {integer}
         * @param callback {function}
         */

    };

    Kernel.prototype.execute = function (code, callbacks, options) {
        /**
         * Execute given code into kernel, and pass result to callback.
         *
         * @async
         * @function execute
         * @param {string} code
         * @param [callbacks] {Object} With the following keys (all optional)
         *      @param callbacks.shell.reply {function}
         *      @param callbacks.shell.payload.[payload_name] {function}
         *      @param callbacks.iopub.output {function}
         *      @param callbacks.iopub.clear_output {function}
         *      @param callbacks.input {function}
         * @param {object} [options]
         *      @param [options.silent=false] {Boolean}
         *      @param [options.user_expressions=empty_dict] {Dict}
         *      @param [options.allow_stdin=false] {Boolean} true|false
         *
         * @example
         *
         * The options object should contain the options for the execute
         * call. Its default values are:
         *
         *      options = {
         *        silent : true,
         *        user_expressions : {},
         *        allow_stdin : false
         *      }
         *
         * When calling this method pass a callbacks structure of the
         * form:
         *
         *      callbacks = {
         *       shell : {
         *         reply : execute_reply_callback,
         *         payload : {
         *           set_next_input : set_next_input_callback,
         *         }
         *       },
         *       iopub : {
         *         output : output_callback,
         *         clear_output : clear_output_callback,
         *       },
         *       input : raw_input_callback
         *      }
         *
         * Each callback will be passed the entire message as a single
         * arugment.  Payload handlers will be passed the corresponding
         * payload and the execute_reply message.
         */
        return this.send_shell_message("execute_request", content, callbacks);
    };

    /**
     * When calling this method, pass a function to be called with the
     * `complete_reply` message as its only argument when it arrives.
     *
     * `complete_reply` is documented
     * [here](https://jupyter-client.readthedocs.io/en/latest/messaging.html#complete)
     *
     * @function complete
     * @param code {string}
     * @param cursor_pos {integer}
     * @param callback {function}
     */
    Kernel.prototype.complete = function (code, cursor_pos, callback) {

        return this.send_shell_message("complete_request", content, callbacks);
    };

    /**
     * @function send_input_reply
     */
    Kernel.prototype.send_input_reply = function (input) {
        return msg.header.msg_id;
    };

    /**
     * @function register_iopub_handler
     */
    Kernel.prototype.register_iopub_handler = function (msg_type, callback) {
        this._iopub_handlers[msg_type] = callback;
    };

    /**
     * Get the iopub handler for a specific message type.
     *
     * @function get_iopub_handler
     */
    Kernel.prototype.get_iopub_handler = function (msg_type) {
        return this._iopub_handlers[msg_type];
    };

    /**
     * Get callbacks for a specific message.
     *
     * @function get_callbacks_for_msg
     */
    Kernel.prototype.get_callbacks_for_msg = function (msg_id) {

    };

    /**
     * Clear callbacks for a specific message.
     *
     * @function clear_callbacks_for_msg
     */
    Kernel.prototype.clear_callbacks_for_msg = function (msg_id) {
        if (this._msg_callbacks[msg_id] !== undefined ) {
            delete this._msg_callbacks[msg_id];
        }
    };
    
    /**
     * @function _finish_shell
     */
    Kernel.prototype._finish_shell = function (msg_id) {

    };

    /**
     * @function _finish_iopub
     */
    Kernel.prototype._finish_iopub = function (msg_id) {

    };
    
    /**
     * Set callbacks for a particular message.
     * Callbacks should be a struct of the following form:
     * shell : {
     * 
     * }
     *
     * @function set_callbacks_for_msg
     */
    Kernel.prototype.set_callbacks_for_msg = function (msg_id, callbacks) {

    };
    
    Kernel.prototype._handle_ws_message = function (e) {

    };

    Kernel.prototype._finish_ws_message = function (msg) {

    };
    
    Kernel.prototype._handle_shell_reply = function (reply) {
        return promise;
    };

    /**
     * @function _handle_payloads
     */
    Kernel.prototype._handle_payloads = function (payloads, payload_callbacks, msg) {
        return Promise.all(promise);
    };

    /**
     * @function _handle_status_message
     */
    Kernel.prototype._handle_status_message = function (msg) {
       
    };
    
    /**
     * Handle clear_output message
     *
     * @function _handle_clear_output
     */
    Kernel.prototype._handle_clear_output = function (msg) {

    };

    /**
     * handle an output message (execute_result, display_data, etc.)
     *
     * @function _handle_output_message
     */
    Kernel.prototype._handle_output_message = function (msg) {

    };

    /**
     * Handle an input message (execute_input).
     *
     * @function _handle_input message
     */
    Kernel.prototype._handle_input_message = function (msg) {

    };

    /**
     * Dispatch IOPub messages to respective handlers. Each message
     * type should have a handler.
     *
     * @function _handle_iopub_message
     */
    Kernel.prototype._handle_iopub_message = function (msg) {

    };

    /**
     * @function _handle_input_request
     */
    Kernel.prototype._handle_input_request = function (request) {

    };

    return {'Kernel': Kernel};
});

参考文章:
http://blog.just4fun.site/jupyter-notebook-architecture.html
http://blog.just4fun.site/jupyter-notebook-architecture-hack.html
https://www.tuicool.com/articles/naqIza
http://flamepeak.com/2016/09/12/Jupyter-official-docs-translate-20160912/
https://jupyter-client.readthedocs.io/en/latest/messaging.html#messaging
http://jupyter-notebook.readthedocs.io/en/stable/comms.html
http://hyry.dip.jp/tech/slice/slice.html/36
http://jupyter-notebook.readthedocs.io/en/stable/examples/Notebook/Connecting%20with%20the%20Qt%20Console.html?highlight=messaging#The-Frontend/Kernel-Model
https://github.com/junjunwudi/zmq-pykernel
https://media.readthedocs.org/pdf/jupyter-notebook/4.x/jupyter-notebook.pdf
https://github.com/ipython/ipython/wiki/IPEP-16%3A-Notebook-multi-directory-dashboard-and-URL-mapping#create_new_notebook
https://stackoverflow.com/questions/26435653/how-do-i-embed-an-ipython-notebook-in-an-iframe-new
http://www.tornadoweb.org/en/stable/web.html#request-handlers
http://jupyter-client.readthedocs.io/en/latest/messaging.html#custom-messages
http://jupyter-notebook.readthedocs.io/en/latest/extending/handlers.html
http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml
http://Check.torproject.org
https://gist.github.com/disarticulate/d06069ff3e71cf828e5329beab8cb084
https://stackoverflow.com/questions/31357718/ipython-javascript-client-api/42418784#42418784
https://www.cnblogs.com/lxtblogs/p/4947898.html
http://jupyter-client.readthedocs.io/en/latest/messaging.html
http://jupyter-notebook.readthedocs.io/en/latest/frontend_config.html#configuring-the-notebook-frontend
http://ipython.org/ipython-doc/stable/development/messaging.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容