|
| 1 | +========================== |
| 2 | +Making kernels for IPython |
| 3 | +========================== |
| 4 | + |
| 5 | +A 'kernel' is a program that runs and introspects the user's code. IPython |
| 6 | +includes a kernel for Python code, and people have written kernels for |
| 7 | +`several other languages <https://github.com/ipython/ipython/wiki/Projects-using-IPython#list-of-some-ipython-compatible-kernels>`_. |
| 8 | + |
| 9 | +When IPython starts a kernel, it passes it a connection file. This specifies |
| 10 | +how to set up communications with the frontend. |
| 11 | + |
| 12 | +There are two options for writing a kernel: |
| 13 | + |
| 14 | +1. You can reuse the IPython kernel machinery to handle the communications, and |
| 15 | + just describe how to execute your code. This is much simpler if the target |
| 16 | + language can be driven from Python. See :doc:`wrapperkernels` for details. |
| 17 | +2. You can implement the kernel machinery in your target language. This is more |
| 18 | + work initially, but the people using your kernel might be more likely to |
| 19 | + contribute to it if it's in the language they know. |
| 20 | + |
| 21 | +Connection files |
| 22 | +================ |
| 23 | + |
| 24 | +Your kernel will be given the path to a connection file when it starts (see |
| 25 | +:ref:`kernelspecs` for how to specify the command line arguments for your kernel). |
| 26 | +This file, which is accessible only to the current user, will contain a JSON |
| 27 | +dictionary looking something like this:: |
| 28 | + |
| 29 | + { |
| 30 | + "control_port": 50160, |
| 31 | + "shell_port": 57503, |
| 32 | + "transport": "tcp", |
| 33 | + "signature_scheme": "hmac-sha256", |
| 34 | + "stdin_port": 52597, |
| 35 | + "hb_port": 42540, |
| 36 | + "ip": "127.0.0.1", |
| 37 | + "iopub_port": 40885, |
| 38 | + "key": "a0436f6c-1916-498b-8eb9-e81ab9368e84" |
| 39 | + } |
| 40 | + |
| 41 | +The ``transport``, ``ip`` and five ``_port`` fields specify five ports which the |
| 42 | +kernel should bind to using `ZeroMQ <http://zeromq.org/>`_. For instance, the |
| 43 | +address of the shell socket in the example above would be:: |
| 44 | + |
| 45 | + tcp://127.0.0.1:57503 |
| 46 | + |
| 47 | +New ports are chosen at random for each kernel started. |
| 48 | + |
| 49 | +``signature_scheme`` and ``key`` are used to cryptographically sign messages, so |
| 50 | +that other users on the system can't send code to run in this kernel. See |
| 51 | +:ref:`wire_protocol` for the details of how this signature is calculated. |
| 52 | + |
| 53 | +Handling messages |
| 54 | +================= |
| 55 | + |
| 56 | +After reading the connection file and binding to the necessary sockets, the |
| 57 | +kernel should go into an event loop, listening on the hb (heartbeat), control |
| 58 | +and shell sockets. |
| 59 | + |
| 60 | +:ref:`Heartbeat <kernel_heartbeat>` messages should be echoed back immediately |
| 61 | +on the same socket - the frontend uses this to check that the kernel is still |
| 62 | +alive. |
| 63 | + |
| 64 | +Messages on the control and shell sockets should be parsed, and their signature |
| 65 | +validated. See :ref:`wire_protocol` for how to do this. |
| 66 | + |
| 67 | +The kernel will send messages on the iopub socket to display output, and on the |
| 68 | +stdin socket to prompt the user for textual input. |
| 69 | + |
| 70 | +.. seealso:: |
| 71 | + |
| 72 | + :doc:`messaging` |
| 73 | + Details of the different sockets and the messages that come over them. |
| 74 | + |
| 75 | + |
| 76 | +.. _kernelspecs: |
| 77 | + |
| 78 | +Kernel specs |
| 79 | +============ |
| 80 | + |
| 81 | +A kernel identifies itself to IPython by creating a directory, the name of which |
| 82 | +is used as an identifier for the kernel. These may be created in a number of |
| 83 | +locations: |
| 84 | + |
| 85 | ++--------+--------------------------------------+-----------------------------------+ |
| 86 | +| | Unix | Windows | |
| 87 | ++========+======================================+===================================+ |
| 88 | +| System | ``/usr/share/ipython/kernels`` | ``%PROGRAMDATA%\ipython\kernels`` | |
| 89 | +| | | | |
| 90 | +| | ``/usr/local/share/ipython/kernels`` | | |
| 91 | ++--------+--------------------------------------+-----------------------------------+ |
| 92 | +| User | ``~/.ipython/kernels`` | |
| 93 | ++--------+--------------------------------------+-----------------------------------+ |
| 94 | + |
| 95 | +The user location takes priority over the system locations, and the case of the |
| 96 | +names is ignored, so selecting kernels works the same way whether or not the |
| 97 | +filesystem is case sensitive. |
| 98 | + |
| 99 | +Inside the directory, the most important file is *kernel.json*. This should be a |
| 100 | +JSON serialised dictionary containing the following keys and values: |
| 101 | + |
| 102 | +- **argv**: A list of command line arguments used to start the kernel. The text |
| 103 | + ``{connection_file}`` in any argument will be replaced with the path to the |
| 104 | + connection file. |
| 105 | +- **display_name**: The kernel's name as it should be displayed in the UI. |
| 106 | + Unlike the kernel name used in the API, this can contain arbitrary unicode |
| 107 | + characters. |
| 108 | +- **language**: The programming language which this kernel runs. This will be |
| 109 | + stored in notebook metadata. This may be used by syntax highlighters to guess |
| 110 | + how to parse code in a notebook, and frontends may eventually use it to |
| 111 | + identify alternative kernels that can run some code. |
| 112 | +- **codemirror_mode** (optional): The `codemirror mode <http://codemirror.net/mode/index.html>`_ |
| 113 | + to use for code in this language. This can be a string or a dictionary, as |
| 114 | + passed to codemirror config. The string from *language* will be used if this is |
| 115 | + not provided. |
| 116 | +- **env** (optional): A dictionary of environment variables to set for the kernel. |
| 117 | + These will be added to the current environment variables before the kernel is |
| 118 | + started. |
| 119 | +- **help_links** (optional): A list of dictionaries, each with keys 'text' and |
| 120 | + 'url'. These will be displayed in the help menu in the notebook UI. |
| 121 | + |
| 122 | +For example, the kernel.json file for IPython looks like this:: |
| 123 | + |
| 124 | + { |
| 125 | + "argv": ["python3", "-c", "from IPython.kernel.zmq.kernelapp import main; main()", |
| 126 | + "-f", "{connection_file}"], |
| 127 | + "codemirror_mode": { |
| 128 | + "version": 3, |
| 129 | + "name": "ipython" |
| 130 | + }, |
| 131 | + "display_name": "IPython (Python 3)", |
| 132 | + "language": "python" |
| 133 | + } |
| 134 | + |
| 135 | +To see the available kernel specs, run:: |
| 136 | + |
| 137 | + ipython kernelspec list |
| 138 | + |
| 139 | +To start the terminal console or the Qt console with a specific kernel:: |
| 140 | + |
| 141 | + ipython console --kernel bash |
| 142 | + ipython qtconsole --kernel bash |
| 143 | + |
| 144 | +To use different kernels in the notebook, select a different kernel from the |
| 145 | +dropdown menu in the top-right of the UI. |
0 commit comments