Jupyter

Jupyter#

Jupyter is a set of tools for developing and sharing scientific code with description. See the official website.

IPython#

ipython actually exists separately from jupyter. But the most common way to use it as the backend for jupyter notebooks, that’s why this tool udner jupyter section. Find out more at the corresponding page.

Client/kernel#

Jupyter has a client/server architecture. All commands are executed by the server - so called jupyter kernel. Client only sends code to be executed - receives and displays the output.

See more on the corresponding Kernel and Client pages. In some cases you can use the special tool that starts the kernel and connects the client to it jupyter_client.KernelManager.


The following cell shows the creation of the KernelManager instance.

from jupyter_client import KernelManager
km = KernelManager(kernel_name="python3")
km.start_kernel()

kc = km.client()
kc.start_channels()

Kernel is a separate process, to which you can send code you want to execute and wait for the response. The following cell makes exactly that.

kc.execute("print(f'hello from kernel {10 + 99}')", reply=True)
msg = kc.get_iopub_msg()
while True:
   msg = kc.get_iopub_msg(timeout=5)
   if msg['msg_type'] == 'stream':
        break

Once we have received the response, we can check it.

print(msg["content"]["text"])
hello from kernel 109

Expected output for the code we sent to kernel to execute.

Kernel must be shut down:

kc.shutdown(reply=True)
km.shutdown_kernel(now=True)

Traitlets#

Traitlets is a tool that allows to make python objects that, automatically check types, autamatically change values of attributes and implement “on change” callbacks. It designed to be used in general, but jet I haven’t seen usage anywhere else except Jupyter project. Check out the traitlest github page. Practically if you want to dive deep into customizing your jupyter workflow you have to learn it.


To get an idea what traitlets are in general consider an example using the traitlets.HasTraits class, which only allows to build classes that automatically validate type, set dynamic default value for the instances and set up methods that will be called in an attemt to change the attribute.

The following cell defines the traitlets.HasTraitlet ancestor with the value attribute, the _default_value method sets up rules which default value value will have, _observe_value is a method that will be callled on an attempt to change the value of value.

import random
import traitlets

class MyFirstTraitlet(traitlets.HasTraits): 
    value = traitlets.Int()

    @traitlets.default("value")
    def _default_value(self):
        return random.randint(1, 100)
    
    @traitlets.observe("value")
    def _observe_value(self, change):
        print(f"Invoked to change: {change["old"]} to {change["new"]}")

The following cell creates the number of MyFirstTraitlet and displays value for them.

for i in range(3):
    obj = MyFirstTraitlet()
    print(obj.value)
56
29
54

Each time there is a different default value for the instance - just as specified in the _default_value method.

The following cell attemts to create MyFirstTrait instance and set value with a str datatype.

try:
    MyFirstTraitlet(value="string")
except Exception as e:
    print(f"Exception: {e}")
Exception: The 'value' trait of a MyFirstTraitlet instance expected an int, not the str 'string'.

But due to the value defined as traitlets.Int it doesn’t allow to set string value to it.

The following cell attempts to change change the value.

traitlet = MyFirstTraitlet()
traitlet.value = 10
Invoked to change: 0 to 10

As a result there will be a message in the output that defined by the _observe_value method.