Ganimede executes code through a Jupyter kernel, giving you the full power of IPython with real-time output streaming. Every cell runs in a shared kernel session, so variables and imports persist across executions.
Jupyter kernel integration
Ganimede uses jupyter_client to manage a kernel process:
from jupyter_client.manager import AsyncKernelManager
class Kernel :
def __init__ ( self , comms : Comms, ydoc : Y.YDoc) -> None :
self .kernel_manager = AsyncKernelManager()
self .kernel_client = None
self .run_queue = asyncio.Queue()
The kernel starts automatically when you execute your first cell.
Execution flow
When you run a cell, Ganimede:
Queues the cell
The cell enters the run queue and its state changes to “queued”
Starts kernel if needed
If no kernel is running, Ganimede starts one automatically
Sends code to kernel
The cell’s code is submitted to the Jupyter kernel client
Streams outputs
Outputs appear in real-time as the kernel generates them
Updates execution count
The cell receives an execution count when complete
Cell states
Cells transition through these states during execution:
Cell is not running and has no queued execution
Cell is waiting in the execution queue
Cell code is currently executing in the kernel
The kernel itself has a busy state that coordinates with cell execution:
@ property
def busy ( self ):
return self ._busy
@busy.setter
def busy ( self , value ):
self ._busy = value
with self .ydoc.begin_transaction() as t:
self .ykernel.set(t, "busy" , value)
Output types
Ganimede handles all standard Jupyter output types:
Text output
Plain text output from print() statements:
output = {
"output_type" : "stream" ,
"name" : "stdout" ,
"text" : [ "Hello, world! \n " ]
}
Rich display data
Images, plots, HTML, and other rich media:
output = {
"output_type" : "display_data" ,
"data" : {
"text/plain" : [ "<Figure size 640x480>" ],
"image/png" : [ "iVBORw0KGgoAAAANS..." ]
},
"metadata" : {}
}
Errors and tracebacks
Exceptions with full stack traces:
output = {
"output_type" : "error" ,
"ename" : "NameError" ,
"evalue" : "name 'x' is not defined" ,
"traceback" : [
" \u001b [0;31m--------------------------------------------------------------------------- \u001b [0m" ,
" \u001b [0;31mNameError \u001b [0m: name 'x' is not defined"
]
}
When an error occurs, Ganimede automatically clears the execution queue to prevent cascade failures.
Execution queue
Cells execute sequentially through a queue system:
async def run_queue_loop ( self ):
while True :
cell_id = await self .run_queue.get()
self ._change_cell_state(cell_id, "running" )
self ._clear_outputs(cell_id)
await self .run(cell_id)
with self .ydoc.begin_transaction() as t:
self .ydoc.get_array( "run_queue" ).delete(t, 0 )
This ensures:
Cells run in the order they’re queued
Only one cell executes at a time
The kernel state stays consistent
You can queue multiple cells by running them in sequence. They’ll execute one after another automatically.
Interrupting execution
If a cell is taking too long or you need to stop execution:
async def interrupt ( self ):
await self .kernel_manager.interrupt_kernel()
Interrupting clears the execution queue and sends a keyboard interrupt to the kernel.
Restarting the kernel
Reset the kernel state without losing your canvas layout:
async def restart_kernel ( self ):
if self .kernel_client is None :
return
try :
await self .kernel_manager.restart_kernel()
except Exception as e:
log.error(e)
self .kernel_client = None
Restarting the kernel clears all variables, imports, and defined functions. You’ll need to re-run cells to rebuild your environment.
Real-time output streaming
Outputs stream to your cell as the kernel generates them:
async def proc_io_msgs () -> None :
self .busy = True
while self .busy:
try :
msg = await self .kernel_client.get_iopub_msg( timeout = 1 )
if msg[ "msg_type" ] == "status" :
if msg[ "content" ][ "execution_state" ] == "idle" :
self .busy = False
else :
msg = self ._msg_to_output(msg)
msg_queue.put_nowait(msg)
except queue.Empty:
pass
This gives you immediate feedback on long-running operations like training models or processing large datasets.
Next steps
Cell management Learn about cell types and properties
Configuration Configure output display settings