Running Python in the Web Browser

A significant part of the project I am currently working on involves executing code submitted by the user. Every bone in my body screams at the fact that the project will accept code from the user and then execute it. A good chunk of the past 20 years I’ve spent as a web developer has revolved around hardening web projects so that user input is NEVER executable.

To solve this problem, I have investigated many different options. One of the great things about working at a university is that research and development are given very high priority. This has given me ample opportunities to learn and experiment with a wide variety of technologies. One technology that I came across was a project by Mozilla called Pyodide.

What is Pyodide?

From this article:

“Pyodide is an experimental project from Mozilla to create a full Python data science stack that runs entirely in the browser.”

Let that sink in. Pyodide allows Python code (and a number of the most powerful modules) to run entirely in the browser. No downloading and installing software. No worrying about multiple versions on the user’s machine. No executing user code on the server!

Mozilla was able to make this magic happen by utilizing WebAssembly. WebAssembly allows C and Rust code to be compiled and run within a web browser. The wizards over at Mozilla were able to use the cpython-emscripten project to convert the Python interpreter into WebAssembly. Python becomes a first class citizen in the browser similar to JavaScript.

Sample Code

This project can be found at https://github.com/ToddLichty/pyodide_test

I used the Ace Code Editor component in this sample since it is quick to embed and makes writing Python in a web browser feel more like writing in an IDE.

After writing code in the editor, clicking the Run Code!!! Button will execute the code in the Pyodide WASM compiler. The print statements are sent to the browser console by default, so I have to tie into the console log event to cause the output to show in the textarea above.

If we look at the project, you can see that Pyodide requires a few different files to work:

These files can be downloaded from the Pyodide website or built on your computer from the GitHub repository.

These files are not small. The WASM file itself is 9.5MB. However, with some clever caching, the user would only need to download the file once.

During the investigation of Pyodide, I was able to put it through it’s paces. I had to try and anticipate any coding issues that a user could make. Besides the standard syntax errors, I tested infinite loops, deep recursion, infinite recursion, mutual recursion etc. Stressing the WASM interpreter like this did cause the browser to crash pretty consistently. Is this an issue with Pyodide. No. The standard Python interpreter behaved the same way when running the same tests.

One issue that became apparent was that running code in Pyodide was approximately 10x slower than running it natively. Below are the results of some of the tests that were run.

Algorithm Native Pyodide
Recursive Fibonaci (35th element) 2626 26273
Prime factors of 67867979 3437 46551
Mutual Recursion 8669 83319

Pyodide is a really cool project. Hopefully, this is the start of possibly moving away from JavaScript and towards potentially using Python for client side scripting instead.