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.