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.