Python Environments

Obit FedDDL supports Python environments using Pyodide, which is a port of CPython that works in the browser. We pin Pyodide v0.27.7 and Python support may be enabled via the Workload initializationOptions object.

Learn by doing?

See an example workload of Pyodide here (DQN on the Pendulum environment via the Gymnasium python package)

Caveats

Note that this support is provided via a virtual machine running via WebAssembly in the browser, which means that it may not have support for all packages. Additionally, some CPU features such as SIMD (SSE/AVX/NEON) may not be available, and GPU passthrough is not supported. For this reason, it is recommended for performance-dependent applications to rewrite the environment in Obit-native syntax (using the Environment API).

Unsupported / risky packages

  • Anything requiring native extensions (C/C++/Fortran) not prebuilt for Pyodide (most of NumPy/SciPy stack is available, but many ML libs are not).

  • GPU-backed packages (CUDA, ROCm), OpenCL, Vulkan — GPU passthrough is not supported.

  • Packages that spawn processes or rely on POSIX syscalls not present in the browser sandbox.

  • Large wheels pulled from PyPI at runtime may exceed browser memory or fetch limits; prefer small, pure-Python deps.

Minimal example

initialization.js
const initializationOptions = {
	pyodide: {
		enabled: true,
		packages: ["micropip"], // optional extra packages
	}
};

// In your workload (RL example):
const autovectorizeInfo = { enabled: true };

const session = new ReinforcementLearningSession(
	ACTION_COUNT,
	TOTAL_SAMPLES,
	TOTAL_ROUNDS,
	BATCH_SIZE,
	EPOCHS_PER_ROUND,
	MIN_CLIENTS_TO_START,
	model,
	Environment,            // JS or Python-wrapped env
	initializationOptions,
	AlgorithmClass,
	algorithmConfig,
	autovectorizeInfo
);

On the client, Pyodide is initialized when initializationOptions.pyodide.enabled is true. Additional packages listed in packages are loaded via micropip (keep these minimal to avoid long load times).

Structuring a Python Environment class

The current pattern for Python environments mirrors the JS Environment API:

  • Define a Python class named Environment with methods:

    • __init__(self, config: dict) — accept only serializable config.

    • reset(self) — returns the initial state (list/tuple of numbers); may be awaited on the JS side.

    • step(self, action) — returns a dict with keys state, reward, done (and optionally info, truncated).

  • Avoid capturing globals; keep the class self-contained. No file I/O, sockets, or multiprocessing.

  • Keep computation lightweight; heavy numeric code may be slow in Pyodide. Prefer pure Python + minimal NumPy where available.

  • Return plain Python lists/tuples/numbers; avoid custom objects in the step/reset payloads.

Example sketch (Python, to be executed inside Pyodide):

Integration notes

  • Package loading: only list small, pure-Python deps in initializationOptions.pyodide.packages; large wheels can stall or fail. If a package is missing in Pyodide’s index, it likely won’t work.

  • Performance: Pyodide runs in WASM; no SIMD/GPU guarantees. For performance-critical envs, prefer implementations using the Obit Environment API.

  • Logging/metrics semantics are unchanged. Env outputs are consumed by the existing JS algorithm/runtime and logged as usual.

Status

Python environments are experimental and best-effort. Expect breakage with some packages or Pyodide updates.

Last updated