🕹️ Try the demo

jupyterlite-pyodide-lock#

Build reproducible Jupyter Lite sites with jupyterlite-pyodide-kernel and pyodide-lock.

docs

install

build

docs

install from pypi install from conda-forge

build

View the full documentation on ReadTheDocs.

Overview#

jupyterlite-pyodide-lock avoids run time pyodide and jupyterlite package management ambiguity by using a full web browser at build time to customize a pyodide-lock.json.

Examples#

Use jupyterlite-pyodide-lock to minimally provide a more controlled baseline pyodide runtime environment, or ensure complex dependencies like widgets are consistent over time.

Minimal Example#

Ensure pyodide-kernel's dependencies are locked, assuming pip and firefox.

Create the Minimal Build Environment#

  • make a requirements.txt

    jupyterlite-core ==0.5.1
    jupyterlite-pyodide-kernel ==0.5.2
    jupyterlite-pyodide-lock ==0.1.2
    
  • Run:

    pip install -r requirements.txt
    

Configure the Minimal Site#

  • build a jupyter_lite_config.json:

    {
      "PyodideLockAddon": {
        "enabled": true
      }
    }
    

Build the Minimal Site#

  • build a jupyter_lite_config.json:

    jupyter lite build
    

Check the Minimal Site Works#

  • start a simple, local development server

    cd _output
    python -m http.server -b 127.0.0.1
    
  • visit the site at http://127.0.0.1:8000/

  • make a new Notebook

    • use basic python features

Widgets Example#

Build a JupyterLite site with all the packages needed to run ipywidgets in a Notebook, assuming mamba.

Create the Widget Build Environment#

  • make an environment.yml

    channels:
      - conda-forge
      - nodefaults
    dependencies:
      - ipywidgets ==8.1.5
      - jupyterlite-core ==0.5.1
      - jupyterlite-pyodide-kernel ==0.5.2
      - jupyterlite-pyodide-lock-recommended ==0.1.2
    
    • the -recommended package includes firefox and geckodriver

    • optionally use a tool like conda-lock or pixi to create a lockfile for the build environment

  • Run:

    mamba env update --file environment.yml --prefix .venv
    source activate .venv # or just `activate .venv` on windows
    

Configure the Widgets Site#

  • build a jupyter_lite_config.json:

    {
      "PyodideLockAddon": {
        "enabled": true,
        "constraints": ["traitlets ==5.14.3"],
        "specs": ["ipywidgets ==8.1.5"],
        "extra_preload_packages": ["ipywidgets"],
        "bootstrap_wheels": [
          "https://files.pythonhosted.org/packages/py3/m/micropip/micropip-0.9.0-py3-none-any.whl"
        ]
      },
      "PyodideLockOfflineAddon": {
        "enabled": true
      }
    }
    
    • note the tight ipywidgets pin, ensuring compatibility with the build environment

    • while not required, the constraints option allows for controlling transient dependencies

      • this feature requires micropip >=0.9.0, which is only compatible with pyodide >=0.27

Build the Site with Widgets#

  • build a jupyter_lite_config.json:

    jupyter lite build
    

Check Widgets Works Offline#

  • disconnect from the internet ✈️

    • this step is optional, but is the most reliable way to validate a reproducible site

  • start a simple, local development server

    cd _output
    python -m http.server -b 127.0.0.1
    
  • visit the site at http://127.0.0.1:8000/

  • make a new Notebook

    • see that ipywidgets can be imported, and widgets work:

      import ipywidgets
      ipywidgets.FloatSlider()
      

Motivation#

  • By default, a pyodide distribution provides a precise set of hundreds of package versions known to work together in the browser, described in its pyodide-lock.json.

  • Among these packages is micropip, which gives site users the ability to install packages not included in pyodide-lock.json. These may be served along with an HTML page, downloaded from PyPI, or anywhere on the internet. jupyterlite-pyodide-kernel uses this capability to install itself, and its dependencies.

    • At run time, piplite provides a micropip-based shim for the IPython %pip magic, the most portable approach for interactive package management in Notebook documents.

  • micropip (and %pip) are powerful for interactive usage, but can cause headaches when upstream versions (or their dependencies) change in ways that either no longer provide the same API expected by the exact versions of pyodide, pyodide-kernel, and JupyterLab extensions in a deployed JupyterLite site.

jupyterlite-pyodide-lock gives content authors tools to manage their effective pyodide distribution, making it easier to build, verify, and maintain predictable, interactive computing environments for future site visitors.

Why Use This?#

  • in the browser

    • fetches pyodide-kernel, its dependencies, and configured packages in parallel while pyodide is starting, skipping micropip.install and its requests to the PyPI API

    • doesn’t require %pip install for locked packages and their dependencies

      • notebooks and scripts still need to be well-formed, e.g. import my_package

      • once shipped, package versions loaded in the browser won’t change over time

  • during a build

    • doesn’t require rebuilding a full custom pyodide distribution

      • but will patch an custom deployed pyodide

      • all downloaded wheels can be optionally shipped along with the application

    • optionally clamp PyPI packages to a known timestamp to ensure newer packages aren’t found during a future solve

    • supports multiple sources of custom wheels and dependencies

Feature Comparison#

A number of approaches are available for getting reproducible JupyterLite runtime python environments, either with jupyterlite-pyodide-kernel or other kernels. Choosing one requires some trades of simplicity, reproducibility, flexibility, and performance.

⏱️ Note

Each tool is evolving, so the tables below should be verified against the different tools when making a decision.

A visitor to a JupyterLite site's needs may be the top priority...

feature

jupyterlite-pyodide-lock

piplite

jupyterlite-xeus

micropip

needs separate install and import

no (for locked packages)

yes (%pip)

no

no

allows install by PyPI name

yes

yes

yes

yes

allows install from URL

yes

yes

no

yes

blocks interaction per package

run cell

run cell

start kernel

run cell

caches in the browser

per package

per package

whole environment

per package

An author of a JupyterLite site may have additional needs...

feature

jupyterlite-pyodide-lock

piplite

jupyterlite-xeus

pyodide-build

requires “heavy” build dependencies

real browser (and/or selenium)

no

minimal, see repo

many, see repo

ships local wheels

yes

yes

maybe?

yes

ships noarch PyPI wheels

yes

yes

yes

yes

ships pyodide emscripten wheels

yes

yes

no

yes

ships arbitrary pyodide zip C libs

no

yes

no

yes

locks multiple versions of same package

no

yes

no

no

optionally clamp to a timestamp

yes

no

no

no

Documentation Contents#