##// END OF EJS Templates
Merge pull request #6978 from takluyver/nbconvert-script...
Merge pull request #6978 from takluyver/nbconvert-script Nbconvert to script for any kernel language

File last commit:

r18471:b4a3f46c
r19053:38e12544 merge
Show More
kernels.rst
137 lines | 5.5 KiB | text/x-rst | RstLexer
Thomas Kluyver
Add docs on writing kernels
r17286 ==========================
Making kernels for IPython
==========================
A 'kernel' is a program that runs and introspects the user's code. IPython
includes a kernel for Python code, and people have written kernels for
`several other languages <https://github.com/ipython/ipython/wiki/Projects-using-IPython#list-of-some-ipython-compatible-kernels>`_.
When IPython starts a kernel, it passes it a connection file. This specifies
how to set up communications with the frontend.
There are two options for writing a kernel:
1. You can reuse the IPython kernel machinery to handle the communications, and
just describe how to execute your code. This is much simpler if the target
language can be driven from Python. See :doc:`wrapperkernels` for details.
2. You can implement the kernel machinery in your target language. This is more
work initially, but the people using your kernel might be more likely to
contribute to it if it's in the language they know.
Connection files
================
Your kernel will be given the path to a connection file when it starts (see
:ref:`kernelspecs` for how to specify the command line arguments for your kernel).
This file, which is accessible only to the current user, will contain a JSON
dictionary looking something like this::
{
"control_port": 50160,
"shell_port": 57503,
"transport": "tcp",
"signature_scheme": "hmac-sha256",
"stdin_port": 52597,
"hb_port": 42540,
"ip": "127.0.0.1",
"iopub_port": 40885,
"key": "a0436f6c-1916-498b-8eb9-e81ab9368e84"
}
The ``transport``, ``ip`` and five ``_port`` fields specify five ports which the
kernel should bind to using `ZeroMQ <http://zeromq.org/>`_. For instance, the
address of the shell socket in the example above would be::
tcp://127.0.0.1:57503
New ports are chosen at random for each kernel started.
``signature_scheme`` and ``key`` are used to cryptographically sign messages, so
that other users on the system can't send code to run in this kernel. See
:ref:`wire_protocol` for the details of how this signature is calculated.
Handling messages
=================
After reading the connection file and binding to the necessary sockets, the
kernel should go into an event loop, listening on the hb (heartbeat), control
and shell sockets.
:ref:`Heartbeat <kernel_heartbeat>` messages should be echoed back immediately
on the same socket - the frontend uses this to check that the kernel is still
alive.
Messages on the control and shell sockets should be parsed, and their signature
validated. See :ref:`wire_protocol` for how to do this.
The kernel will send messages on the iopub socket to display output, and on the
stdin socket to prompt the user for textual input.
.. seealso::
:doc:`messaging`
Thomas Kluyver
Add more see also entries
r17295 Details of the different sockets and the messages that come over them
`Creating Language Kernels for IPython <http://andrew.gibiansky.com/blog/ipython/ipython-kernels/>`_
A blog post by the author of `IHaskell <https://github.com/gibiansky/IHaskell>`_,
a Haskell kernel
`simple_kernel <https://github.com/dsblank/simple_kernel>`_
A simple example implementation of the kernel machinery in Python
Thomas Kluyver
Add docs on writing kernels
r17286
.. _kernelspecs:
Kernel specs
============
A kernel identifies itself to IPython by creating a directory, the name of which
is used as an identifier for the kernel. These may be created in a number of
locations:
+--------+--------------------------------------+-----------------------------------+
| | Unix | Windows |
+========+======================================+===================================+
| System | ``/usr/share/ipython/kernels`` | ``%PROGRAMDATA%\ipython\kernels`` |
| | | |
| | ``/usr/local/share/ipython/kernels`` | |
+--------+--------------------------------------+-----------------------------------+
| User | ``~/.ipython/kernels`` |
+--------+--------------------------------------+-----------------------------------+
The user location takes priority over the system locations, and the case of the
names is ignored, so selecting kernels works the same way whether or not the
filesystem is case sensitive.
Inside the directory, the most important file is *kernel.json*. This should be a
JSON serialised dictionary containing the following keys and values:
- **argv**: A list of command line arguments used to start the kernel. The text
``{connection_file}`` in any argument will be replaced with the path to the
connection file.
- **display_name**: The kernel's name as it should be displayed in the UI.
Unlike the kernel name used in the API, this can contain arbitrary unicode
characters.
- **env** (optional): A dictionary of environment variables to set for the kernel.
These will be added to the current environment variables before the kernel is
started.
For example, the kernel.json file for IPython looks like this::
{
"argv": ["python3", "-c", "from IPython.kernel.zmq.kernelapp import main; main()",
Thomas Kluyver
Update docs about kernelspecs and kernel_info_reply
r18471 "-f", "{connection_file}"],
Thomas Kluyver
Add docs on writing kernels
r17286 "display_name": "IPython (Python 3)",
}
To see the available kernel specs, run::
ipython kernelspec list
To start the terminal console or the Qt console with a specific kernel::
ipython console --kernel bash
ipython qtconsole --kernel bash
To use different kernels in the notebook, select a different kernel from the
dropdown menu in the top-right of the UI.