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