How to Use Python in your Browser/Webapps

Published

Python is a very versatile language, thanks to being a dynamically typed interpreted language but it can be lacking in terms of creating a nice User Interface.

One possibility is to interface your Python script with Javascript and other Web Languages. In this article, I present 3 ways to enable the use of Python in that context, so you can use your python logic in a website, webapp or Electron desktop app.

Server-Side Python

The first possibility is to require the user, or your server, to have a Python install, with all the necessary dependencies. Then you can make a javascript script call your python scripts using the child_process package.

This is what I did in my VisualMidi project:

  • Write a function that calls the python script (which analyzes a midi file) and returns the data in a Promise
  • Create an Express Server exposing endpoints which will execute the function above and then return the data
  • Specify a function for use in your app to query the Express Server for the data, and trigger the UI update accordingly

The function calling the Python and script and returning the data looks like this:

const { spawn } = require("child_process");

const logOutput = (name) => (message) => console.log(`[${name}] ${message}`);

const analyzeSong = function (filename) {
  return new Promise((resolve, reject) => {
    const process = spawn("python", ["./Analyzer.py", filename]);

    const out = [];
    process.stdout.on("data", (data) => {
      out.push(data.toString());
      logOutput("stdout")(data);
    });

    const err = [];
    process.stderr.on("data", (data) => {
      err.push(data.toString());
      logOutput("stderr")(data);
    });

    process.on("exit", (code, signal) => {
      logOutput("exit")(`${code} (${signal})`);
      if (code !== 0) {
        reject(new Error(err.join("\n")));
        return;
      }
      try {
        resolve(JSON.parse(out[0]));
      } catch (e) {
        reject(e);
      }
    });
  });
};

This method requires quite a bit of boilerplate, but to be honest it works much better than I initially expected.

An important point to note: it’s better for the Python output to be serialised as a JSON, it makes it easier to interface with it in Javascript.

You could also just go full Python for the server to avoid all this pain, but if you’re working in a team or already have a server running this is a good alternative.

Client-Side Python, with interpreter loaded

The next possibility is to load an interpreter in the browser. This is the approach taken by Brython.

I think this is a great approach as Brython allows you to directly interface with the DOM (aka the elements making up a webpage), so you can set text and styles directly using Python. You can also load packages and use them in the browser so it’s really great.

The main drawback of this approach though is the size of the interpreter: you’ll need a javascript for a size of around ~2-3mb.

While this is more or less ok on desktop, it will be painful for mobile users which might give up on using your product if it takes too long to load: consider using a Loading Screen.

Finally, there will be performance costs, as Brython makes heavy of Python’s Meta-Programming capabilities with the eval function, as is referenced in this issue: https://github.com/brython-dev/brython/issues/1419

Transpile Python to Javascript

Finally, the last solution I have to propose is Transpiling your Python package to Javascript, which means generating valid Javascript code from Python. This is doable through the use of the Transcrypt package.

I intend to write a fully detailed report on my experience with Transcrypt since I have used it to successfully transpile my MusiStrata library.

Still here are some information on the package to help you make your decision:

Pros Cons
It works for non trivial projects Only Python 3
Small Javascript files generated, so Kb instead of Mb with Brython Errors Messages can be of little use
Very Performant Operator overloading is problematic (wrong operator usage with radd)
Backwards Compatibility of some packages can break the transpiling (had problems with the Enum Package)

Conclusion

With all this, you should now be able to use your python scripts in web apps, or distribute them with Electron.

To note: if your only motivation to use Python in the browser is that you don’t want to learn Javascript, you should realize that using Python in the browser is far from being the most efficient method.

But, if you have a complex package or script that cannot be trivially ported to Javascript (lack of time/money/skills, or the project is just too complex), the 3 options are great alternatives. They each have their own drawbacks but one of them will fit your needs.