Skip to content

Execution model

Molt gives each tab a long-lived Python subprocess for the duration of that kernel session.

A tab’s cells share one global namespace in one process. Assignments, imports, function definitions, and object mutations remain available to later executions in that tab:

records = []
records.append({"status": "ready"})

A later cell can evaluate:

records
[{'status': 'ready'}]

Another tab cannot see records, because it uses another process with another globals dictionary.

Molt prepares Tab 1 when the application starts. It prepares another tab when you select or run it. After you stop a tab, Molt does not start it again until you select Restart.

All four tabs use the interpreter selected when Molt started.

A tab executes one cell at a time. Different tabs have different Python processes, so they can run independently.

Run All waits for each nonempty cell before starting the next. It stops when a cell fails or when you stop, restart, or clear the tab.

Python parsing and final-expression display

Section titled “Python parsing and final-expression display”

Molt runs the statements in a cell, then displays the representation of a final bare expression when its value is not None. The displayed value is also available as _ in later cells in that tab.

This is why a cell ending in items displays the representation of items, while a cell ending in items.append(value) displays nothing when append returns None.

This is plain Python behavior, not IPython. Magics, shell escapes, top-level notebook helpers, and rich display hooks are absent.

Molt captures:

  • Captured standard output.
  • Captured standard error.
  • A formatted traceback for ordinary exceptions.
  • An output type currently fixed to text.

Standard output and standard error are collected separately, so their original interleaving is not preserved. Molt displays standard output first, then standard error, then an error traceback.

During cell execution, sys.stdin is replaced with an empty text stream so user code cannot consume the JSON control channel. Calls to input() raise EOFError.

Ordinary exceptions are caught and returned as text. The Python process remains available, and mutations that occurred before the exception may remain in the namespace.

An interrupted cell shows a KeyboardInterrupt error. If the interruption completes cleanly, the tab can keep using the same Python state. Restart the tab if it remains unavailable.

SystemExit and other BaseException subclasses are returned as cell errors, so calls such as sys.exit() do not terminate the kernel server.

  • Restart kills the process and creates a fresh one for that tab.
  • Stop kills the process and leaves a stopped marker that blocks execution until Restart.
  • App shutdown drains the kernel map and kills every remaining child process.
  • Child processes are also configured with kill-on-drop as an additional cleanup boundary.

No kernel namespace is serialized. Reproducibility requires restarting and rerunning source cells in order.