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