Skip to main content

Snapshot-Kernel

A Snapshotting Kernel for Python

Luca de Alfaro, 2026

snapshot-kernel is a snapshotting kernel, mainly geared at executing Jupyter Python notebooks. The kernel stores execution states. Executing code from a state generates a new state. In this way, it is possible to store the state after executing each cell of a notebook, and to return to that state if we need to re-execute the cell. The API is implemented as a REST API using bottle.py, and results in very fast startup and shutdown times.

Kernel Basics

The kernel stores states, where a state is a snapshot of the execution environment, including among others:

  • Timestamp when the state was created
  • Variables
  • Imported modules

States are immutable. They are not modified; however, new states can be created from existing states by executing code in that state.

The kernel stores states in the form of a dictionary mapping state names to their content. The main methods that the kernel implements are:

  • execute(code: str, exec_id: str, state_name: str, new_state_name: Optional[str] = None): dict: Executes the given code in the specified state. exec_id is a unique ID for this execution. If new_state_name is provided, the resulting state after execution will be stored under that name. Otherwise, the resulting state will be stored under a new randomly generated unique name. The output of the execution should be a dictionary including at least:

    • output: The output of the execution, if any, as a list in the same format as the output of a Jupyter notebook cell execution.
    • state_name: The name of the state after execution.
    • error: Any error that occurred during execution, if applicable.
    • accessed_symbols: The list of top-level variable names that were present in the state before execution and were read during the execution (the cell's dependencies on pre-existing variables), e.g. ["df", "x"]. Names the cell itself defines are not included. On interpreters where read-tracking cannot be relied upon, this conservatively lists all pre-existing symbols. multistate_execute returns this same accessed_symbols key.
    • modified_symbols: The list of top-level variable names assigned during execution (the cell's writes), e.g. ["y"]. Best-effort (dunder names and the injected display helper are excluded).
    • deleted_symbols: The list of top-level variable names removed with del during execution.
  • get_state(state_name: str) -> dict: Retrieves the state associated with the given name. The state should include all variables and imported modules at that point in execution.

  • get_symbol_hashes(state_name: str, symbols: List[str], hash_algo: Optional[str] = None) -> dict: Returns a dict mapping each requested symbol to a stable content hash of its value in the given state, used to detect whether symbols changed between states. hash_algo selects the strategy; currently only "full" is supported (the default when None), which hashes the full value (pickled bytes, SHA-256). Symbols absent from the state map to null; returns None (HTTP 404) if the state does not exist. Exposed over HTTP as POST /symbol_hashes with body {state_name, symbols, hash_algo?}, returning {"hashes": {...}}.

  • get_alias_groups(state_name: str) -> dict: Returns {"groups": [[names...], ...], "fingerprints": [hex, ...]} — the alias groups of the state (maximal sets of top-level variables that share a mutable object, directly or nested) and, for each group, a fingerprint that hashes the group's members together (so it reflects both their values and the sharing among them). Every non-dunder user variable appears in exactly one group (singletons included). Returns None (HTTP 404) if the state does not exist. Exposed as POST /alias_groups with body {state_name}.

  • rebuild_state(input_state: str, source_state: str, source_vars: List[str], input_vars: List[str], new_state_name: Optional[str] = None) -> dict: Reconstructs a successor state without executing code: the variables in source_vars are copied from source_state, the variables in input_vars from input_state, each side under its own shared deepcopy memo (so aliasing within each side is preserved). The caller must guarantee the two sides are alias-disjoint. Returns {state_name, groups, fingerprints} for the new state, or None (HTTP 404) if either state is missing. Exposed as POST /rebuild_state with body {input_state, source_state, source_vars, input_vars, new_state_name?}.

  • list_states() -> List[str]: Returns a list of all state names currently stored in the kernel.

  • delete_state(state_name: str): Deletes the state associated with the given name from the kernel.

  • reset(): Resets the kernel by clearing all stored states and returning to an initial empty state.

  • interrupt(exec_id: str): Interrupts the execution associated with the given exec_id. This should stop the execution of the code and return an appropriate response indicating that the execution was interrupted.

Implementation Details

The kernel is written in Python. The Python code is:

  • Indented with 4-space indentation
  • Type hints not necessary
  • Docstrings should be included.

State snapshots preserve intra-state aliasing: the namespace is deep-copied with a single shared copy.deepcopy memo, so two variables that reference the same object (directly or nested) remain aliased within a state — matching standard Python semantics — while distinct states stay fully independent. Modules are stored by reference.

Output Format

The output generated by the kernel is in a format that is compatible with Jupyter notebook cell outputs. This means that the output is a list of dictionaries, where each dictionary represents an output item and has at least the following keys:

  • output_type: A string indicating the type of output (e.g., "stream", "display_data", "execute_result", "error", etc.).
  • data: The actual output data, which can be in various formats depending on the output type (e.g., text, HTML, images, etc.).
  • metadata: Any additional metadata associated with the output, such as MIME types, execution count, etc.

In particular, the kernel can also capture:

  • Figures / plots generated by the code, such as those generated by matplotlib, should be captured and included in the output in a format that can be rendered in a Jupyter notebook (e.g., as base64-encoded PNG images).
  • Rich outputs, such as those generated by libraries like pandas (e.g., DataFrames), should also be captured and included in the output in a format that can be rendered in a Jupyter notebook (e.g., as HTML tables).

The test cases should include tests for these formats.

Communication with the Kernel

Communication with the kernel occurs over a rest API using HTTP requests, and the bottle.py web server, using cheroot as the WSGI server to enable multi-threading. The multithreading is necessary to allow for interrupting long-running executions. Note that we are also not ruling out the possibility of computing multiple states in parallel, generating multiple output states from the same input state.

The bottle server should be launched with a command of the form:

python -m bottle --bind <IP_ADDRESS>:8080 --token=<SECRET_TOKEN> main.py

where kernel_server.py is the file containing the implementation of the kernel and the bottle server, and SECRET_TOKEN is a token that should be specified as a URL parameter in every request for authentication. The server listens for incoming HTTP requests and route them to the appropriate methods of the kernel based on the request path and method (e.g., POST for executing code, GET for retrieving states, etc.).

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

snapshot_kernel-0.2.0.tar.gz (28.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

snapshot_kernel-0.2.0-py3-none-any.whl (17.4 kB view details)

Uploaded Python 3

File details

Details for the file snapshot_kernel-0.2.0.tar.gz.

File metadata

  • Download URL: snapshot_kernel-0.2.0.tar.gz
  • Upload date:
  • Size: 28.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for snapshot_kernel-0.2.0.tar.gz
Algorithm Hash digest
SHA256 21030e2f1fa8d26aa8c833083f0e700e3d31c7bbdd5f8be3da5ff2bba30fc5fe
MD5 c391c648b300a7eeae5e495c25e74551
BLAKE2b-256 ed01f55f6737c0c203f5f6225b3e4c3a58e4b36b502024dc9ff16c6644f13014

See more details on using hashes here.

File details

Details for the file snapshot_kernel-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for snapshot_kernel-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e09b8fb74a5c190f612c84c23cd6d7ecb262bc5ce7a491d124186425a7c4f188
MD5 f93965675d48dd47e398f48aeb65f8b8
BLAKE2b-256 777867372de128f7db4d6ca34930fb36fe8c7893844816474c984a150b4a9e2a

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.1

2 files

This release

0.2.0 This release

2 files

0.1.4

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page