Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve logic for restarting kernels with new ports during initial startup #348

Open
wants to merge 65 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
d67c82a
Make a start on kernel discovery framework
takluyver May 18, 2017
6406393
Undeprecate KernelManager.kernel_cmd, add extra_env
takluyver May 19, 2017
6ca3ec7
Use entry points to find kernel finders
takluyver Jul 26, 2017
dddda32
Tests for kernel discovery machinery
takluyver Jul 26, 2017
1509dac
Use older ABC definition style with metaclass
takluyver Jul 26, 2017
38ccbdc
Rename kernel finders -> kernel providers
takluyver Oct 9, 2017
3c09a57
Missed a rename
takluyver Oct 9, 2017
e92e5c1
Add dependency on entrypoints
takluyver Oct 9, 2017
aad40cb
Document new kernel providers system
takluyver Oct 10, 2017
c09b8ac
Break it up a bit with a subheading
takluyver Oct 10, 2017
cc8176b
Update doc with Carol's suggestions
takluyver Oct 10, 2017
1f74c5f
Fix variable name
takluyver Oct 10, 2017
8f7a865
Merge pull request #261 from takluyver/discovery
takluyver Oct 16, 2017
16608fc
Fix typo in documentation.
Oct 19, 2017
4776e8c
Merge pull request #299 from didiercrunch/patch-1
takluyver Oct 19, 2017
936dfe0
Updated URL for Jupyter Kernels
frelon Nov 1, 2017
2822872
Merge pull request #300 from frelon/patch-1
blink1073 Nov 1, 2017
aca5f70
tornado 5 support
minrk Nov 10, 2017
172d6cd
Configure interrupt mode via spec.
filmor Sep 21, 2017
f0e33ba
Update docs.
filmor Oct 30, 2017
21b9569
Bump protocol version.
filmor Nov 6, 2017
6674afa
disable pyzmq zero-copy optimizations during session tests
minrk Nov 13, 2017
7a0278a
Merge pull request #304 from minrk/tornado-5
takluyver Nov 13, 2017
e2772bd
Fix signal name.
filmor Nov 13, 2017
0d7d00f
Merge pull request #294 from filmor/interrupt
takluyver Nov 13, 2017
948d653
extend special handling of sys.executable to pythonX[.Y]
minrk Nov 22, 2017
250178f
Add 'jupyter kernel' command
takluyver Feb 10, 2017
9359b33
Use native kernel by default
takluyver Dec 11, 2017
ae03ddd
More description
takluyver Dec 11, 2017
7e6d167
Add test of 'jupyter kernel'
takluyver Dec 11, 2017
28f908f
Workaround lack of timeout on Py2
takluyver Dec 11, 2017
aa8b184
Restrict to older pytest on Python 3.3
takluyver Dec 11, 2017
5291f94
Another go at fixing pytest dependency on Python 3.3
takluyver Dec 11, 2017
7bbb56d
Merge pull request #240 from takluyver/jupyter-kernel-cmd
minrk Dec 12, 2017
16d8122
Merge pull request #306 from minrk/pythonX
takluyver Dec 13, 2017
ed05107
Tolerate invalid kernel specs in get_all_specs()
takluyver Dec 15, 2017
dd4a2d6
Improve performance of get_kernel_spec
takluyver Dec 15, 2017
22092fa
kill process group when killing kernel
minrk Dec 15, 2017
5f076b7
Start writing release notes for 5.2
takluyver Dec 15, 2017
98a4323
Merge pull request #314 from minrk/process-groups
takluyver Dec 15, 2017
6689764
Add PR #314 to changelog
takluyver Dec 15, 2017
adb8335
Merge pull request #311 from takluyver/get-kernel-spec-performance
Carreau Dec 15, 2017
cf36849
Merge pull request #310 from takluyver/get-all-specs-tolerant
Carreau Dec 15, 2017
6251cf6
Add PRs #310 and #311 to changelog
takluyver Dec 16, 2017
a9bd197
Merge pull request #315 from takluyver/changelog-5.2
takluyver Dec 18, 2017
a8b4745
require tornado
minrk Dec 19, 2017
4d1ee2a
Merge pull request #322 from minrk/require-tornado
takluyver Dec 19, 2017
072a087
Parenthesize conditional requirement in setup.py
Carreau Dec 30, 2017
c85f8ac
Merge pull request #325 from Carreau/fix-324
minrk Jan 2, 2018
e426a64
Exclude build docs from sdist.
Carreau Jan 3, 2018
77784a6
Merge pull request #328 from Carreau/no-bundle-docs
blink1073 Jan 3, 2018
41c5954
more complete error message
stonebig Jan 6, 2018
36751d3
Merge pull request #330 from stonebig/patch-1
Carreau Jan 6, 2018
c658076
Tell Travis not to test the push from MrMeeseeks
Carreau Jan 6, 2018
78951c3
Merge pull request #332 from Carreau/ignore-travis-meeseeks
Carreau Jan 7, 2018
cd73530
handle classes having been torn down in atexit
minrk Jan 16, 2018
162cf6f
Merge pull request #336 from minrk/atexit-teardown
takluyver Jan 17, 2018
7d6812f
Add logic for detecting not responding kernels
skukhtichev Jan 29, 2018
4d81491
changed log level for KernelRestarter messages
skukhtichev Jan 29, 2018
5a8e536
enable kernel monitor only if the startup_time > 0
skukhtichev Jan 29, 2018
f655041
Added comments
skukhtichev Jan 29, 2018
2618f08
kernel_monitor_enabled configuration duplicates startup_time configur…
skukhtichev Jan 30, 2018
fe2f546
Check whether callback function supports kwargs
skukhtichev Jan 30, 2018
8d8a5bc
Set default startup_time to 0
skukhtichev Jan 30, 2018
899ec69
Updated logic for kernel monitor
skukhtichev Jan 31, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ after_success:
matrix:
allow_failures:
- python: nightly
branches:
except:
- /^auto-backport-of-pr-[0-9]+$/
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ include README.md
# Documentation
graft docs
exclude docs/\#*
exclude docs/_*

# Examples
graft examples
Expand Down
49 changes: 49 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,55 @@
Changes in Jupyter Client
=========================

5.2.1
=====

- Add parenthesis to conditional pytest requirement to work around a bug in the
``wheel`` package, that generate a ``.whl`` which otherwise always depends on
``pytest`` see :ghissue:`324` and :ghpull:`325`

5.2
===

`5.2 on GitHub <https://github.com/jupyter/jupyter_client/milestones/5.2>`__

- Define Jupyter protocol version 5.3:

- Kernels can now opt to be interrupted by a message sent on the control channel
instead of a system signal. See :ref:`kernelspecs` and :ref:`msging_interrupt`
(:ghpull:`294`).

- New ``jupyter kernel`` command to launch an installed kernel by name
(:ghpull:`240`).
- Kernelspecs where the command starts with e.g. ``python3`` or
``python3.6``—matching the version ``jupyter_client`` is running on—are now
launched with the same Python executable as the launching process (:ghpull:`306`).
This extends the special handling of ``python`` added in 5.0.
- Command line arguments specified by a kernelspec can now include
``{resource_dir}``, which will be substituted with the kernelspec resource
directory path when the kernel is launched (:ghpull:`289`).
- Kernelspecs now have an optional ``metadata`` field to hold arbitrary metadata
about kernels—see :ref:`kernelspecs` (:ghpull:`274`).
- Make the ``KernelRestarter`` class used by a ``KernelManager`` configurable
(:ghpull:`290`).
- When killing a kernel on Unix, kill its process group (:ghpull:`314`).
- If a kernel dies soon after starting, reassign random ports before restarting
it, in case one of the previously chosen ports has been bound by another
process (:ghpull:`279`).
- Avoid unnecessary filesystem operations when finding a kernelspec with
:meth:`.KernelSpecManager.get_kernel_spec` (:ghpull:`311`).
- :meth:`.KernelSpecManager.get_all_specs` will no longer raise an exception on
encountering an invalid ``kernel.json`` file. It will raise a warning and
continue (:ghpull:`310`).
- Check for non-contiguous buffers before trying to send them through ZMQ
(:ghpull:`258`).
- Compatibility with upcoming Tornado version 5.0 (:ghpull:`304`).
- Simplify setup code by always using setuptools (:ghpull:`284`).
- Soften warnings when setting the sticky bit on runtime files fails
(:ghpull:`286`).
- Various corrections and improvements to documentation.


5.1
===

Expand Down
3 changes: 3 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.napoleon',
'sphinxcontrib_github_alt',
]

# Add any paths that contain templates here, relative to this directory.
Expand All @@ -55,6 +56,8 @@
copyright = '2015, Jupyter Development Team'
author = 'Jupyter Development Team'

github_project_url = "https://github.com/jupyter/jupyter_client"

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
Expand Down
2 changes: 2 additions & 0 deletions docs/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ dependencies:
- jupyter_core
- sphinx>=1.3.6
- sphinx_rtd_theme
- pip:
- sphinxcontrib_github_alt
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ with Jupyter kernels.

kernels
wrapperkernels
kernel_providers

.. toctree::
:maxdepth: 2
Expand Down
156 changes: 156 additions & 0 deletions docs/kernel_providers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
================
Kernel providers
================

.. note::
This is a new interface under development, and may still change.
Not all Jupyter applications use this yet.
See :ref:`kernelspecs` for the established way of discovering kernel types.

Creating a kernel provider
==========================

By writing a kernel provider, you can extend how Jupyter applications discover
and start kernels. For example, you could find kernels in an environment system
like conda, or kernels on remote systems which you can access.

To write a kernel provider, subclass
:class:`jupyter_client.discovery.KernelProviderBase`, giving your provider an ID
and overriding two methods.

.. class:: MyKernelProvider

.. attribute:: id

A short string identifying this provider. Cannot contain forward slash
(``/``).

.. method:: find_kernels()

Get the available kernel types this provider knows about.
Return an iterable of 2-tuples: (name, attributes).
*name* is a short string identifying the kernel type.
*attributes* is a dictionary with information to allow selecting a kernel.

.. method:: make_manager(name)

Prepare and return a :class:`~jupyter_client.KernelManager` instance
ready to start a new kernel instance of the type identified by *name*.
The input will be one of the names given by :meth:`find_kernels`.

For example, imagine we want to tell Jupyter about kernels for a new language
called *oblong*::

# oblong_provider.py
from jupyter_client.discovery import KernelProviderBase
from jupyter_client import KernelManager
from shutil import which

class OblongKernelProvider(KernelProviderBase):
id = 'oblong'

def find_kernels(self):
if not which('oblong-kernel'):
return # Check it's available

# Two variants - for a real kernel, these could be something like
# different conda environments.
yield 'standard', {
'display_name': 'Oblong (standard)',
'language': {'name': 'oblong'},
'argv': ['oblong-kernel'],
}
yield 'rounded', {
'display_name': 'Oblong (rounded)',
'language': {'name': 'oblong'},
'argv': ['oblong-kernel'],
}

def make_manager(self, name):
if name == 'standard':
return KernelManager(kernel_cmd=['oblong-kernel'],
extra_env={'ROUNDED': '0'})
elif name == 'rounded':
return KernelManager(kernel_cmd=['oblong-kernel'],
extra_env={'ROUNDED': '1'})
else:
raise ValueError("Unknown kernel %s" % name)

You would then register this with an *entry point*. In your ``setup.py``, put
something like this::

setup(...
entry_points = {
'jupyter_client.kernel_providers' : [
# The name before the '=' should match the id attribute
'oblong = oblong_provider:OblongKernelProvider',
]
})

Finding kernel types
====================

To find and start kernels in client code, use
:class:`jupyter_client.discovery.KernelFinder`. This uses multiple kernel
providers to find available kernels. Like a kernel provider, it has methods
``find_kernels`` and ``make_manager``. The kernel names it works
with have the provider ID as a prefix, e.g. ``oblong/rounded`` (from the example
above).

::

from jupyter_client.discovery import KernelFinder
kf = KernelFinder.from_entrypoints()

## Find available kernel types
for name, attributes in kf.find_kernels():
print(name, ':', attributes['display_name'])
# oblong/standard : Oblong (standard)
# oblong/rounded : Oblong(rounded)
# ...

## Start a kernel by name
manager = kf.make_manager('oblong/standard')
manager.start_kernel()

.. module:: jupyter_client.discovery

.. autoclass:: KernelFinder

.. automethod:: from_entrypoints

.. automethod:: find_kernels

.. automethod:: make_manager

Kernel providers included in ``jupyter_client``
===============================================

``jupyter_client`` includes two kernel providers:

.. autoclass:: KernelSpecProvider

.. seealso:: :ref:`kernelspecs`

.. autoclass:: IPykernelProvider

Glossary
========

Kernel instance
A running kernel, a process which can accept ZMQ connections from frontends.
Its state includes a namespace and an execution counter.

Kernel type
The software to run a kernel instance, along with the context in which a
kernel starts. One kernel type allows starting multiple, initially similar
kernel instances. For instance, one kernel type may be associated with one
conda environment containing ``ipykernel``. The same kernel software in
another environment would be a different kernel type. Another software package
for a kernel, such as ``IRkernel``, would also be a different kernel type.

Kernel provider
A Python class to discover kernel types and allow a client to start instances
of those kernel types. For instance, one kernel provider might find conda
environments containing ``ipykernel`` and allow starting kernel instances in
these environments.
9 changes: 8 additions & 1 deletion docs/kernels.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Making kernels for Jupyter

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/IPython-kernels-for-other-languages>`_.
`several other languages <https://github.com/jupyter/jupyter/wiki/Jupyter-kernels>`_.

When Jupyter starts a kernel, it passes it a connection file. This specifies
how to set up communications with the frontend.
Expand Down Expand Up @@ -132,6 +132,13 @@ JSON serialised dictionary containing the following keys and values:
is found, a kernel with a matching `language` will be used.
This allows a notebook written on any Python or Julia kernel to be properly associated
with the user's Python or Julia kernel, even if they aren't listed under the same name as the author's.
- **interrupt_mode** (optional): May be either ``signal`` or ``message`` and
specifies how a client is supposed to interrupt cell execution on this kernel,
either by sending an interrupt ``signal`` via the operating system's
signalling facilities (e.g. `SIGINT` on POSIX systems), or by sending an
``interrupt_request`` message on the control channel (see
:ref:`msging_interrupt`). If this is not specified
the client will default to ``signal`` mode.
- **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.
Expand Down
23 changes: 22 additions & 1 deletion docs/messaging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Versioning

The Jupyter message specification is versioned independently of the packages
that use it.
The current version of the specification is 5.2.
The current version of the specification is 5.3.

.. note::
*New in* and *Changed in* messages in this document refer to versions of the
Expand Down Expand Up @@ -959,6 +959,27 @@ Message type: ``shutdown_reply``::
socket, they simply send a forceful process termination signal, since a dead
process is unlikely to respond in any useful way to messages.

.. _msging_interrupt:

Kernel interrupt
----------------

In case a kernel can not catch operating system interrupt signals (e.g. the used
runtime handles signals and does not allow a user program to define a callback),
a kernel can choose to be notified using a message instead. For this to work,
the kernels kernelspec must set `interrupt_mode` to ``message``. An interruption
will then result in the following message on the `control` channel:

Message type: ``interrupt_request``::

content = {}

Message type: ``interrupt_reply``::

content = {}

.. versionadded:: 5.3


Messages on the IOPub (PUB/SUB) channel
=======================================
Expand Down
2 changes: 1 addition & 1 deletion jupyter_client/_version.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
version_info = (5, 1, 0)
__version__ = '.'.join(map(str, version_info))

protocol_version_info = (5, 2)
protocol_version_info = (5, 3)
protocol_version = "%i.%i" % protocol_version_info
5 changes: 4 additions & 1 deletion jupyter_client/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ def __init__(self, context=None, session=None, address=None):
@staticmethod
@atexit.register
def _notice_exit():
HBChannel._exiting = True
# Class definitions can be torn down during interpreter shutdown.
# We only need to set _exiting flag if this hasn't happened.
if HBChannel is not None:
HBChannel._exiting = True

def _create_socket(self):
if self.socket is not None:
Expand Down
Loading