wrapperkernels.rst
175 lines
| 6.0 KiB
| text/x-rst
|
RstLexer
Thomas Kluyver
|
r16859 | Making simple Python wrapper kernels | ||
==================================== | ||||
.. versionadded:: 3.0 | ||||
You can now re-use the kernel machinery in IPython to easily make new kernels. | ||||
This is useful for languages that have Python bindings, such as `Octave | ||||
<http://www.gnu.org/software/octave/>`_ (via | ||||
Thomas Kluyver
|
r23220 | `Oct2Py <http://blink1073.github.io/oct2py/>`_), or languages | ||
谭九鼎
|
r26565 | where the REPL can be controlled in a tty using `pexpect <https://pexpect.readthedocs.io/en/latest/>`_, | ||
Thomas Kluyver
|
r16859 | such as bash. | ||
Thomas Kluyver
|
r17295 | .. seealso:: | ||
`bash_kernel <https://github.com/takluyver/bash_kernel>`_ | ||||
A simple kernel for bash, written using this machinery | ||||
Thomas Kluyver
|
r16859 | Required steps | ||
-------------- | ||||
Min RK
|
r21636 | Subclass :class:`ipykernel.kernelbase.Kernel`, and implement the | ||
Thomas Kluyver
|
r16859 | following methods and attributes: | ||
.. class:: MyKernel | ||||
.. attribute:: implementation | ||||
implementation_version | ||||
language | ||||
language_version | ||||
banner | ||||
Information for :ref:`msging_kernel_info` replies. 'Implementation' refers | ||||
to the kernel (e.g. IPython), and 'language' refers to the language it | ||||
interprets (e.g. Python). The 'banner' is displayed to the user in console | ||||
UIs before the first prompt. All of these values are strings. | ||||
Thomas Kluyver
|
r18471 | .. attribute:: language_info | ||
Language information for :ref:`msging_kernel_info` replies, in a dictionary. | ||||
This should contain the key ``mimetype`` with the mimetype of code in the | ||||
Thomas Kluyver
|
r18968 | target language (e.g. ``'text/x-python'``), and ``file_extension`` (e.g. | ||
``'py'``). | ||||
It may also contain keys ``codemirror_mode`` and ``pygments_lexer`` if they | ||||
need to differ from :attr:`language`. | ||||
Thomas Kluyver
|
r18471 | |||
Other keys may be added to this later. | ||||
Thomas Kluyver
|
r16859 | .. method:: do_execute(code, silent, store_history=True, user_expressions=None, allow_stdin=False) | ||
Execute user code. | ||||
:param str code: The code to be executed. | ||||
:param bool silent: Whether to display output. | ||||
:param bool store_history: Whether to record this code in history and | ||||
increase the execution count. If silent is True, this is implicitly | ||||
False. | ||||
:param dict user_expressions: Mapping of names to expressions to evaluate | ||||
after the code has run. You can ignore this if you need to. | ||||
:param bool allow_stdin: Whether the frontend can provide input on request | ||||
(e.g. for Python's :func:`raw_input`). | ||||
Your method should return a dict containing the fields described in | ||||
:ref:`execution_results`. To display output, it can send messages | ||||
Min RK
|
r21636 | using :meth:`~ipykernel.kernelbase.Kernel.send_response`. | ||
Thomas Kluyver
|
r16859 | See :doc:`messaging` for details of the different message types. | ||
Thomas Kluyver
|
r16964 | To launch your kernel, add this at the end of your module:: | ||
if __name__ == '__main__': | ||||
Min RK
|
r21636 | from ipykernel.kernelapp import IPKernelApp | ||
Thomas Kluyver
|
r16964 | IPKernelApp.launch_instance(kernel_class=MyKernel) | ||
Example | ||||
------- | ||||
``echokernel.py`` will simply echo any input it's given to stdout:: | ||||
Min RK
|
r21636 | from ipykernel.kernelbase import Kernel | ||
Thomas Kluyver
|
r16964 | |||
Thomas Kluyver
|
r17095 | class EchoKernel(Kernel): | ||
Thomas Kluyver
|
r16964 | implementation = 'Echo' | ||
implementation_version = '1.0' | ||||
language = 'no-op' | ||||
language_version = '0.1' | ||||
Thomas Kluyver
|
r18471 | language_info = {'mimetype': 'text/plain'} | ||
Thomas Kluyver
|
r16964 | banner = "Echo kernel - as useful as a parrot" | ||
Doug Blank
|
r17619 | def do_execute(self, code, silent, store_history=True, user_expressions=None, | ||
Thomas Kluyver
|
r16964 | allow_stdin=False): | ||
if not silent: | ||||
Doug Blank
|
r18463 | stream_content = {'name': 'stdout', 'text': code} | ||
Thomas Kluyver
|
r16964 | self.send_response(self.iopub_socket, 'stream', stream_content) | ||
return {'status': 'ok', | ||||
# The base class increments the execution count | ||||
'execution_count': self.execution_count, | ||||
'payload': [], | ||||
'user_expressions': {}, | ||||
} | ||||
if __name__ == '__main__': | ||||
Min RK
|
r21636 | from ipykernel.kernelapp import IPKernelApp | ||
Thomas Kluyver
|
r16964 | IPKernelApp.launch_instance(kernel_class=EchoKernel) | ||
Here's the Kernel spec ``kernel.json`` file for this:: | ||||
{"argv":["python","-m","echokernel", "-f", "{connection_file}"], | ||||
Matthias Bussonnier
|
r19548 | "display_name":"Echo" | ||
Thomas Kluyver
|
r16964 | } | ||
Thomas Kluyver
|
r16859 | |||
Optional steps | ||||
-------------- | ||||
You can override a number of other methods to improve the functionality of your | ||||
kernel. All of these methods should return a dictionary as described in the | ||||
relevant section of the :doc:`messaging spec <messaging>`. | ||||
Matthias Bussonnier
|
r25610 | .. class:: MyBetterKernel | ||
Thomas Kluyver
|
r16859 | |||
.. method:: do_complete(code, cusor_pos) | ||||
Code completion | ||||
:param str code: The code already present | ||||
:param int cursor_pos: The position in the code where completion is requested | ||||
.. seealso:: | ||||
:ref:`msging_completion` messages | ||||
.. method:: do_inspect(code, cusor_pos, detail_level=0) | ||||
Thomas Kluyver
|
r17003 | Object introspection | ||
Thomas Kluyver
|
r16859 | |||
:param str code: The code | ||||
Thomas Kluyver
|
r17003 | :param int cursor_pos: The position in the code where introspection is requested | ||
Thomas Kluyver
|
r16859 | :param int detail_level: 0 or 1 for more or less detail. In IPython, 1 gets | ||
the source code. | ||||
.. seealso:: | ||||
:ref:`msging_inspection` messages | ||||
.. method:: do_history(hist_access_type, output, raw, session=None, start=None, stop=None, n=None, pattern=None, unique=False) | ||||
Thomas Kluyver
|
r16973 | History access. Only the relevant parameters for the type of history | ||
request concerned will be passed, so your method definition must have defaults | ||||
for all the arguments shown with defaults here. | ||||
Thomas Kluyver
|
r16859 | |||
.. seealso:: | ||||
:ref:`msging_history` messages | ||||
Thomas Kluyver
|
r17625 | .. method:: do_is_complete(code) | ||
Is code entered in a console-like interface complete and ready to execute, | ||||
or should a continuation prompt be shown? | ||||
:param str code: The code entered so far - possibly multiple lines | ||||
.. seealso:: | ||||
:ref:`msging_is_complete` messages | ||||
Thomas Kluyver
|
r16859 | .. method:: do_shutdown(restart) | ||
Shutdown the kernel. You only need to handle your own clean up - the kernel | ||||
machinery will take care of cleaning up its own things before stopping. | ||||
:param bool restart: Whether the kernel will be started again afterwards | ||||
.. seealso:: | ||||
:ref:`msging_shutdown` messages | ||||