In parallel to the Python 3 port of ViUR, our free application development framework for the Google App Engine platform, we also did some experimenting with an alternative for our PyJS-based administration tool VI.

The experiments where successful: Pyodide, a project serving a Python 3.7 interpreter compiled to web-assembly (WASM) provides a flexible, fast and powerful solution to even build web-apps written in pure Python. A first attempot of porting the Vi to Python 3 running on top of Pyodide looks very promising. This is a short presentation about what Pyodide is, what we changed and how future work might look like...

Start presentation

What is Pyodide?

  • Pyodide brings the Python runtime to the browser via WebAssembly
  • CPython 3.7 interpreter compiled to WASM
  • emscripten SDK + tools used for building


Some caveats...

  • The pyodide binaries (pyodide runtime + cpython) is ~22 MB of download
  • Browser prohibits network sockets
  • Cannot be served as static folder in app.yaml right now because of invalid mime-types
  • Therefore CSP-rule unsafe-eval must be set to allow calling JS from Python (e.g.

Examples: Run Python from JavaScript

// Simple Python
var x = pyodide.runPython("import sys\nsys.version");
console.log(x); // <- 3.7.0 (default, Jul  2 2019, 11:27:08) [Clang 6.0.1 ]

// Asynchronous: First load packages, then run code
from jinja2 import Environment, BaseLoader

tpl = Environment(loader=BaseLoader).from_string("<h1>{{title|upper}}</h1>")
print(tpl.render(title="Hello World"))

Examples: Run JavaScript from Python

from js import window, eval as jseval

document = window.document = "Hello World"
jseval("alert('Help me!')")

remotePath feature

  • Problem: Python packages must be pre-build and packed using pyodide_build
  • Solution: remotePath-Feature (
  • Let Pyodide look for Python source files as modules
  • pyodide.remotePath allows setting several locations to remotely look for packages
  • Import fetched packages into browser emulated local file system (emscripten FS)
  • Let Python import files as usual from there
  • Perfect for debugging, porting and plugins!
pyodide.remotePath = ["/", ""];
pyodide.runPythonAsync("import vi");

Porting the Vi

  • basic porting was generally easy and done in a few hours: Edit Python file + F5
  • html5, logics and vi itself can later be packaged (for installation with setuptools)
  • Some minor changes to the ViUR project has to be done (as long as mime-types for static folders are wrong)
  • develop -> redesign -> pyodide is current branch order


  • Vi can be provided as a stand-alone package: Unpack and run!
  • Porting of other, existing web-apps needs only a couple of hours, especially using the remotePath-feature
  • Pre-compiled packages and pure Python code can be intermixed in projects (e.g. standard & pre-packaged Vi, extended to custom plugins)
  • Eventually pre-caching / pre-build possible for faster app startup in mobile apps / app containers?
  • The html5 library and ignite could be merged to serve as a general UI toolkit for HTML5-based web-apps written in Python and run on Pyodide
  • We can start RIGHT NOW!

Thank you!

Any questions?