This PEP proposes a new platform tag seriespyodide for binary Python packagedistributions for the Pyodide Python runtime.
Emscripten is a complete open-source compilertoolchain. It compiles C/C++ code into WebAssembly/JavaScript executables, foruse in JavaScript runtimes, including browsers and Node.js. The Rust languagealso maintains an Emscripten target.PEP 776 specifies Python’s support forEmscripten.
Pyodide is a CPython distribution for use in the browser. A web browser is auniversal computing platform, available on Windows, macOS, Linux, and everysmartphone. Hundreds of thousands of students have learned Python throughPyodide via projects likeCapytaleandPyodideU. Pyodideis also increasingly being used by Python packages to provide interactivedocumentation.
Pyodide currently maintains ports of 255 different packages at the time of thiswriting, including major scientific Python packages like NumPy, SciPy, pandas,Polars, scikit-learn, OpenCV, PyArrow, and Pillow as well as general purposepackages like aiohttp, Requests, Pydantic, cryptography, and orjson.
About 60 packages are also testing against Pyodide in their CI, including NumPy,pandas, awkward-cpp, scikit-image, statsmodels, PyArrow, Hypothesis, and PyO3.
Python package projects cannot deploy binary distributions for Pyodide on PyPI.Instead they must use other options likeanaconda.org orjsdelivr.com.This creates friction both for package maintainers and for users.
Emscripten uses a variant of musl libc. The Emscripten compiler makes no ABIstability guarantees between versions. Many Emscripten updates are ABIcompatible by chance, and the Rust Emscripten target behaves as if the ABI werestable with onlyoccasional negative consequences.
There are several linker flags that adjust the Emscripten ABI, so Pythonpackages built to run with Emscripten must make sure to match the ABI-sensitivelinker flags used to compile the interpreter to avoid load-time or run-timeerrors. The Emscripten compiler continuously fixes bugs and adds support for newweb platform features. Thus, there is significant benefit to being able toupdate the ABI.
In order to balance the ABI stability needs of package maintainers with the ABIflexibility to allow the platform to move forward, Pyodide plans to adopt a newABI for each feature release of Python.
The Pyodide team also coordinates the ABI flags that Pyodide uses with theEmscripten ABI that Rust supports in order to ensure that we have support forthe many popular Rust packages. Historically, most of the work for this hasbeen related to unwinding ABIs. See for instancethis Rust Major ChangeProposal.
Thepyodide platform tags only apply to Python interpreters compiled andlinked with the same version of Emscripten as Pyodide, with the sameABI-sensitive flags.
The platform tags will take the form:
pyodide_${YEAR}_${PATCH}_wasm32Each one of these will be used with a specified Python version. For example, theplatform tagpyodide_2025_0 will be used with Python 3.13.
The specification of thepyodide_<abi> platform includes:
-pthread-sWASM_BIGINTThe ABI is selected by choosing the appropriate version of the Emscriptencompiler and passing appropriate compiler and linker flags. It is possible forother people to build their own Python interpreter that is compatible with thePyodide ABI, it is not necessary to use the Pyodide distribution itself.
The Pyodide ABIs are fully specified in thePyodide Platform ABI documentation.
Thepyodidebuild tool knows how to create wheels that match the PyodideABI. Unlike with manylinux wheels, there is no need for a Docker container tobuild thepyodide_<abi> wheels. All that is needed is a Linux machine andappropriate versions of Python, Node.js, and Emscripten.
It is possible to validate a wheel by installing and importing it into thePyodide runtime. Because Pyodide can run in an environment with strongsandboxing guarantees, doing this produces no security risks.
The Pyodide ABI version is stored in thePYODIDE_ABI_VERSION config variableand can be determined via:
pyodide_abi_version=sysconfig.get_config_var("PYODIDE_ABI_VERSION")
To generate the list of compatible tags, one can use the following code:
frompackaging.tagsimportcpython_tags,_generic_platformsdef_emscripten_platforms()->Iterator[str]:pyodide_abi_version=sysconfig.get_config_var("PYODIDE_ABI_VERSION")ifpyodide_abi_version:yieldf"pyodide_{pyodide_abi_version}_wasm32"yield from_generic_platforms()emscripten_tags=cpython_tags(platforms=_emscripten_platforms())
This code will be added topypa/packaging.
Installers should use the_emscripten_platforms() function shown above todetermine which platforms are compatible with an Emscripten build of CPython. Inparticular, the Pyodide ABI version is exposed viasysconfig.get_config_var("PYODIDE_ABI_VERSION").
Package indexes SHOULD accept any wheel whose platform tag matchesthe regular expressionpyodide_[0-9]+_[0-9]+_wasm32.
According toPEP 776, in Emscripten Pythonsys.platform returns"emscripten". To check for the Emscripten platform in adependency specifier, one can usesys_platform=="emscripten" (or itsnegation).
Packages that build and test Emscripten wheels can declare this by adding theEnvironment::WebAssembly::Emscripten classifier. PyPI already accepts uploads ofpackages with this classifier.
There are no backwards compatibility concerns in this PEP.
There are no security implications in this PEP.
For Pyodide users, we recommend thePyodide documentation on installingpackages.
For package maintainers, we recommend thePyodide documentation on building andtesting packages.
For building packages,pyodide build andcibuildwheel.
For installers to decide whether a wheel tag is compatible with a Pyodideinterpreter,pypa/packaging#804.
This document is placed in the public domain or under theCC0-1.0-Universal license, whichever is more permissive.
Source:https://github.com/python/peps/blob/main/peps/pep-0783.rst
Last modified:2025-04-07 10:40:17 GMT