Client

Client#

This section describes how the jupyter client normally works and how to work with different implementations of the jupyter client.


The following cell runs the simpliest IPythonKernlel that is commonly used for experimenting with jupyter clients.

from pathlib import Path
from src.run_jupyter_kernel import IPKernelAppProcess
from jupyter_client.blocking import BlockingKernelClient
from IPython.display import JSON


connection_file = Path("/tmp")/"connection_file.json"
connection_file.unlink(missing_ok=True)
IPKernelAppProcess(connection_file=str(connection_file))
<src.run_jupyter_kernel.IPKernelAppProcess at 0x773b699979e0>
NOTE: When using the `ipython kernel` entry point, Ctrl-C will not work.

To exit, you will have to explicitly quit this process, by either sending
"quit" from a client, or using Ctrl-\ in UNIX-like environments.

To read more about this, see https://github.com/ipython/ipython/issues/2049


To connect another client to this kernel, use:
    --existing /tmp/connection_file.json

Creating client#

The following cell defines the client that we’ll use as an example. You need to pass the connection file to the kernel and call the start_channels method.

client = BlockingKernelClient()
client.load_connection_file(connection_file)
client.start_channels()

The conenction can be checked by using the is_alive method - it must return True.

client.is_alive()
True

Execute#

For execution code, use the execute method to point to code that needs to be executed. It returns msg_id which allows to identify which messages from the kernel correspond to which messages returned by the kernel.

To get messages from the kernel, use the client’s get_iopub_msg method of the client. It consistently returns different messages that correspond to different stages of execution.


The following cell sends some code to be executed by the kernel.

msg_id = client.execute("x = 42\ny = x * 2\ny")
msg_id
'fe6a6eeb-5f12062d2f9dea307db4ff50_36430_0'

The following cell collects all messages generaged by the kernel.

ans_list = []

while True:
    try:
        ans_list.append(client.get_iopub_msg(timeout=5))
    except:
        break

In this case 4 messages were returned by the kernel. There is a lot of duplicated information: what’s importand at this stage is:

  • msg_type: this allows to understand what type of message we got, for example execute_result means that this message.

  • content: the content that the kernel sends to the client - depends on msg_type.

  • header.msg_id: This allows to understand to which message from the client this response belongs to.

ans_list[0]
{'header': {'msg_id': 'b129712b-72dfc25a8727a31966a73369_36544_5',
  'msg_type': 'status',
  'username': 'fedor',
  'session': 'b129712b-72dfc25a8727a31966a73369',
  'date': datetime.datetime(2025, 4, 16, 19, 14, 14, 147446, tzinfo=tzutc()),
  'version': '5.3'},
 'msg_id': 'b129712b-72dfc25a8727a31966a73369_36544_5',
 'msg_type': 'status',
 'parent_header': {'msg_id': 'fe6a6eeb-5f12062d2f9dea307db4ff50_36430_0',
  'msg_type': 'execute_request',
  'username': 'fedor',
  'session': 'fe6a6eeb-5f12062d2f9dea307db4ff50',
  'date': datetime.datetime(2025, 4, 16, 19, 14, 14, 145429, tzinfo=tzutc()),
  'version': '5.3'},
 'metadata': {},
 'content': {'execution_state': 'busy'},
 'buffers': []}
ans_list[1]
{'header': {'msg_id': 'b129712b-72dfc25a8727a31966a73369_36544_6',
  'msg_type': 'execute_input',
  'username': 'fedor',
  'session': 'b129712b-72dfc25a8727a31966a73369',
  'date': datetime.datetime(2025, 4, 16, 19, 14, 14, 147899, tzinfo=tzutc()),
  'version': '5.3'},
 'msg_id': 'b129712b-72dfc25a8727a31966a73369_36544_6',
 'msg_type': 'execute_input',
 'parent_header': {'msg_id': 'fe6a6eeb-5f12062d2f9dea307db4ff50_36430_0',
  'msg_type': 'execute_request',
  'username': 'fedor',
  'session': 'fe6a6eeb-5f12062d2f9dea307db4ff50',
  'date': datetime.datetime(2025, 4, 16, 19, 14, 14, 145429, tzinfo=tzutc()),
  'version': '5.3'},
 'metadata': {},
 'content': {'code': 'x = 42\ny = x * 2\ny', 'execution_count': 1},
 'buffers': []}
ans_list[2]
{'header': {'msg_id': 'b129712b-72dfc25a8727a31966a73369_36544_7',
  'msg_type': 'execute_result',
  'username': 'fedor',
  'session': 'b129712b-72dfc25a8727a31966a73369',
  'date': datetime.datetime(2025, 4, 16, 19, 14, 14, 151135, tzinfo=tzutc()),
  'version': '5.3'},
 'msg_id': 'b129712b-72dfc25a8727a31966a73369_36544_7',
 'msg_type': 'execute_result',
 'parent_header': {'msg_id': 'fe6a6eeb-5f12062d2f9dea307db4ff50_36430_0',
  'msg_type': 'execute_request',
  'username': 'fedor',
  'session': 'fe6a6eeb-5f12062d2f9dea307db4ff50',
  'date': datetime.datetime(2025, 4, 16, 19, 14, 14, 145429, tzinfo=tzutc()),
  'version': '5.3'},
 'metadata': {},
 'content': {'data': {'text/plain': '84'},
  'metadata': {},
  'execution_count': 1},
 'buffers': []}
ans_list[3]
{'header': {'msg_id': 'b129712b-72dfc25a8727a31966a73369_36544_9',
  'msg_type': 'status',
  'username': 'fedor',
  'session': 'b129712b-72dfc25a8727a31966a73369',
  'date': datetime.datetime(2025, 4, 16, 19, 14, 14, 156378, tzinfo=tzutc()),
  'version': '5.3'},
 'msg_id': 'b129712b-72dfc25a8727a31966a73369_36544_9',
 'msg_type': 'status',
 'parent_header': {'msg_id': 'fe6a6eeb-5f12062d2f9dea307db4ff50_36430_0',
  'msg_type': 'execute_request',
  'username': 'fedor',
  'session': 'fe6a6eeb-5f12062d2f9dea307db4ff50',
  'date': datetime.datetime(2025, 4, 16, 19, 14, 14, 145429, tzinfo=tzutc()),
  'version': '5.3'},
 'metadata': {},
 'content': {'execution_state': 'idle'},
 'buffers': []}

Tools#

In the utils.run_jupyter_kernel module there are tools that implement some utilities to work with the jupyter client and avoid boilerplate code in notebooks.


The get_messages function allows to execute some code in the given kernel, catching and returning all messages.

from utils.run_jupyter_kernel import get_messages
get_messages(connection_file=str(connection_file), code="print('hello')")
[{'header': {'msg_id': '8172f864-deac1bd202c2ad241eee2ae2_129765_5',
   'msg_type': 'status',
   'username': 'fedor',
   'session': '8172f864-deac1bd202c2ad241eee2ae2',
   'date': datetime.datetime(2025, 4, 17, 8, 38, 31, 521258, tzinfo=tzutc()),
   'version': '5.3'},
  'msg_id': '8172f864-deac1bd202c2ad241eee2ae2_129765_5',
  'msg_type': 'status',
  'parent_header': {'msg_id': '1a1e0701-a0ca2d36265f355a70edf622_79253_0',
   'msg_type': 'execute_request',
   'username': 'fedor',
   'session': '1a1e0701-a0ca2d36265f355a70edf622',
   'date': datetime.datetime(2025, 4, 17, 8, 38, 31, 520480, tzinfo=tzutc()),
   'version': '5.3'},
  'metadata': {},
  'content': {'execution_state': 'busy'},
  'buffers': []},
 {'header': {'msg_id': '8172f864-deac1bd202c2ad241eee2ae2_129765_6',
   'msg_type': 'execute_input',
   'username': 'fedor',
   'session': '8172f864-deac1bd202c2ad241eee2ae2',
   'date': datetime.datetime(2025, 4, 17, 8, 38, 31, 521728, tzinfo=tzutc()),
   'version': '5.3'},
  'msg_id': '8172f864-deac1bd202c2ad241eee2ae2_129765_6',
  'msg_type': 'execute_input',
  'parent_header': {'msg_id': '1a1e0701-a0ca2d36265f355a70edf622_79253_0',
   'msg_type': 'execute_request',
   'username': 'fedor',
   'session': '1a1e0701-a0ca2d36265f355a70edf622',
   'date': datetime.datetime(2025, 4, 17, 8, 38, 31, 520480, tzinfo=tzutc()),
   'version': '5.3'},
  'metadata': {},
  'content': {'code': "print('hello')", 'execution_count': 1},
  'buffers': []},
 {'header': {'msg_id': '8172f864-deac1bd202c2ad241eee2ae2_129765_7',
   'msg_type': 'stream',
   'username': 'fedor',
   'session': '8172f864-deac1bd202c2ad241eee2ae2',
   'date': datetime.datetime(2025, 4, 17, 8, 38, 31, 523541, tzinfo=tzutc()),
   'version': '5.3'},
  'msg_id': '8172f864-deac1bd202c2ad241eee2ae2_129765_7',
  'msg_type': 'stream',
  'parent_header': {'session': '1a1e0701-a0ca2d36265f355a70edf622',
   'version': '5.3',
   'msg_id': '1a1e0701-a0ca2d36265f355a70edf622_79253_0',
   'username': 'fedor',
   'msg_type': 'execute_request',
   'date': datetime.datetime(2025, 4, 17, 8, 38, 31, 520480, tzinfo=tzutc())},
  'metadata': {},
  'content': {'name': 'stdout', 'text': 'hello\n'},
  'buffers': []},
 {'header': {'msg_id': '8172f864-deac1bd202c2ad241eee2ae2_129765_9',
   'msg_type': 'status',
   'username': 'fedor',
   'session': '8172f864-deac1bd202c2ad241eee2ae2',
   'date': datetime.datetime(2025, 4, 17, 8, 38, 31, 525225, tzinfo=tzutc()),
   'version': '5.3'},
  'msg_id': '8172f864-deac1bd202c2ad241eee2ae2_129765_9',
  'msg_type': 'status',
  'parent_header': {'msg_id': '1a1e0701-a0ca2d36265f355a70edf622_79253_0',
   'msg_type': 'execute_request',
   'username': 'fedor',
   'session': '1a1e0701-a0ca2d36265f355a70edf622',
   'date': datetime.datetime(2025, 4, 17, 8, 38, 31, 520480, tzinfo=tzutc()),
   'version': '5.3'},
  'metadata': {},
  'content': {'execution_state': 'idle'},
  'buffers': []}]