Python on the server and in the browser. Path to Web Assembly

Python as an application development technology is predominantly used for creating automation scripts, creating backend and web applications, as well as for data analysis and use of statistics and machine learning methods. There are also some approaches to creating mobile applications in Python (for example, the engine Kivy over OpenGL for Android). But the niche of using Python applications in a web browser remains unfilled, which could allow transferring part of the data processing directly to the client device and creating full-fledged full-stack applications on the same technology. The solution to this problem can be to cross-compile Python to WebAssembly code, which can be executed both in the browser and on the server using nodejs or the V8 engine, or SSVM (Second State Virtual Machine). In this article, we will look at several approaches to running Python applications inside a browser and server using WebAssembly.

The most important aspect of the implementation is the ability to interact with the runtime environment through the WASI interface (WebAssembly System Interface), which (depending on the environment) provides access to the file system, hardware, data storage, hardware solutions for neural networks, graphics library, etc. Since for Python applications need to provide not only computing capabilities, but also access to environment resources, the WASI implementation aspect is one of the most important and it is with it that there are difficulties in different implementations now.

One option for compiling a Python application to run in the browser is to use emscripten for CPython, but currently it does not support PyPI packages and network requests. Similarly, launching via emscripten in NodeJS does not support packages, but can work with multithreading and signals. To build Python via emscripten in WebAssembly, you can use these scenarios.

The second option is to use specialized wasm runtime implementations (e.g. wasmtime) and compile using their WASI implementations, e.g. for Python: https://enarx.dev/docs/webassembly/python

The most advanced options are Pyodide (supports packets, networking, signals, as well as full access to the file system, access to all browser APIs) and Pygame (supports cross-compilation to WebAssembly and work with graphics and multimedia). To install packages in Pyodide use micropip. Pyodide can be used to run Python inside Javascript code by including https://cdn.jsdelivr.net/pyodide/v0.21.3/full/pyodide.js and run the code snippet:

async function main() {
  let pyodide = await loadPyodide();
  // Pyodide is now ready to use...
  console.log(pyodide.runPython(`
    import sys
    sys.version
  `));
};
main();

You can also use external modules:

await pyodide.loadPackage("numpy");
pyodide.runPython(`
  import numpy
  x=numpy.ones((3, 4))
`);
pyodide.globals.get('x').toJs();

To manipulate DOM objects and access WebAPI, you can connect the js module and access document, window, and other browser objects through it. Also, pyodide provides package ports for networking (from pyodide.http import pyfetch), working with the file system in NodeJS (FS). In addition, Pyodide provides an interface for interacting with wasm code.

The most interesting project is CoWasmwhich provides a set of build tools and ports for many commonly used python libraries (including numpy, pandas, sqlite, posix, openssl, zlib, libgit2) and a Python code runtime in WASM python-wasm. To use python code, you can use both REPL (npx python-wasm) and include it in the code via require:

{syncPython, asyncPython} = require('python-wasm')
python = await syncPython();
python.exec('import numpy')
python.repr('numpy.linspace(0, 10, num=5)')

To implement wasm-ports of packages, the possibilities for compiling the language are used Zig + TypeScript, or compilation via Zig Wasm of the source codes of libraries in C. After compilation, two versions of the modules will be created – native (to be run in a normal python runtime environment) and wasm (to be used in conjunction with a browser / NodeJS). To execute the code in the distribution, you need to run the following commands:

. bin/env.sh
cd packages/python-wasm
./bin/python-wasm

Although it will run Python in the REPL, it is a full-fledged WebAssembly runtime (and this can be checked by querying the system version import sys; sys.version).

The python-wasm package can also be used to execute code in browser:

const python = require("python-wasm");
python.exec('import os')
python.repr('os.version')

An example of using CoWasm in a browser can be viewed here.

For testing covasm, you can also build Docker-container.

The project is actively developing, among the main contributors @bobuk . The main idea of ​​the project is indicated as the possibility of reusing Python code between the client and the server and organizing joint work on the code using the capabilities of WebRTC and other instant data exchange technologies.

To everyone who read the article, I recommend the next open online lessons:

Tonight we will talk about what place SOLID occupies in modern development and how it will be applied in Python. Registration – link.

Tomorrow evening we will learn how to work with built-in modules. Learn about modules (os, pathlib, functools). Registration – link.

Similar Posts

Leave a Reply