Neuigkeiten von trion.
Immer gut informiert.

Python im Browser als WebAssembly ausführen

Es muss nicht immer Javascript sein. Mit dem WebAssembly Standard hat man die Möglichkeit, den Browser als Ablaufumgebung für u.a. auf C, C++, Go, Rust sowie Python basierendem Code zu nutzen.

Wir werden uns dies am Beispiel von Python einmal genauer anhand eines praktischen Beispiels anschauen.

Die Beispielanwendung

Unsere Anwendung ist bewusst schlicht gehalten. Der Nutzer soll im oberen Editor-Textfeld Python-Code eingeben und diesen ausführen lassen können. Die Log-yyAusgabe des Codes erfolgt im unteren Textfeld.

Aufbau der Anwendung

Die Anwendung soll über das Python-Webframework Flask verfügbar gemacht werden. Dazu wird zunächst eine virtuelle Umgebung erzeugt und Flask verfügbar gemacht:

$ mkdir py-webasm
$ cd py-webasm
$ python3 -m venv venv
$ . ./venv/bin/activate
(venv)$ pip install Flask

Install Flask:

(env)$ pip install Flask

templates/index.html beinhaltet die notwendigen Javascript-Bibliotheken und die beschriebenen Textfelder:

<!doctype html>
<html lang="de">
  <title>py-webasm</title>
  <meta charset="UTF-8">
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js"></script>
  <script src="https://cdn.jsdelivr.net/pyodide/v0.21.3/full/pyodide.js"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.8/codemirror.min.css" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.8/codemirror.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.8/mode/python/python.min.js"></script>
</head>
<body>
  <h1>Python Konsole</h1>
  <div>
    <div>
      <label for="code">Eingabe</label><textarea id="code" name="code"></textarea>
    </div>
    <div>
      <label for="output">Ausgabe</label><textarea rows="20" cols="40" readonly id="output" name="output"></textarea>
    </div>
  </div>
  <button onclick="execPythonCode()" type="button">Ausführen</button>
  <script src="/static/js/main.js"></script>
</body>
</html>

Dabei werden die folgenden Javascript-/CSS-Frameworks verwendet:

  • Bootstrap für den grundlegenden Stil

  • Pyodide als Abstraktion für die WebAssembly-basierende Laufzeitumgebung

  • CodeMirror als Code-Editor für unsere Browser-Texteingabe

Nun muss der eingegebene Python-Code - darum geht es schließlich - im Browser ausgeführt werden. Dazu dient die Javascript-Funktion execPythonCode() und das darin verwendete pyodide.runPython():

const output = document.getElementById("output");

const editor = CodeMirror.fromTextArea(
    document.getElementById("code"), {
        mode: {
            name: "python",
            version: 3,
            singleLineStringErrors: false,
        },
        lineNumbers: true,
        indentUnit: 4,
        matchBrackets: true
    }
);
editor.setValue("print('Grüße von der Python!')");

function addToOutput(stdout) {
    output.value += "\n>>> " + stdout;
}

async function main() {
    let pyodide = await loadPyodide({
        indexURL: "https://cdn.jsdelivr.net/pyodide/v0.21.3/full/",
    });
    output.value = pyodide.runPython(`
    import sys
    sys.version
  `);
    return pyodide;
}

let ready = main();

async function execPythonCode() {
    let pyodide = await ready;
    try {
        pyodide.runPython(`
      import io
      sys.stdout = io.StringIO()
    `);
        pyodide.runPython(editor.getValue());
        let stdout = pyodide.runPython("sys.stdout.getvalue()");
        addToOutput(stdout);
    } catch (err) {
        addToOutput(err);
    }
}

Damit ist unsere Anwendung fertig und kann mit der Flask App app.py ausgeliefert werden:

from flask import Flask, render_template

app = Flask(__name__)


@app.route('/')
def render_webasm():
	return render_template('index.html')


if __name__ == '__main__':
	app.run()
$ flask run

Unser kleines Beispiel zeigt die grundsätzliche Machbarkeit und kratzt natürlich nur an der WebAssembly Oberfläche. Kommende Artikel werden etwas mehr an die WebAssembly Grundfesten gehen (Assemblies mittels C/C++, etc.) sowie die Anbindung von pyodide in Richtung Skripten / Zugriff auf das Browser-DOM gehen.


Die im Artikel verwendeten Quelldateien finden Sie hier.




Zu den Themen Python und Webtechnologien bieten wir sowohl Beratung, Entwicklungsunterstützung als auch passende Schulungen an:

Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.

Feedback oder Fragen zu einem Artikel - per Twitter @triondevelop oder E-Mail freuen wir uns auf eine Kontaktaufnahme!

Zur Desktop Version des Artikels