Open In App

Build Python code editor using CodeMirror and pyodide

Last Updated : 22 Nov, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we will learn to develop an application which can run the Python code inside your web browser. 

To achieve this, we will use pyodide.org, which consists of the CPython interpreter compiled to WebAssembly which allows Python to run in the browser. We are going to use codemirror.net in Python-mode as a code-editor component. You can find the API reference and source code links at the end of this article.

Let us take a quick look at our project structure: 

Project Structure

We essentially have two files here, a HTML file, for the user interface and a javascript file, to setup pyodide and CodeMirror. 

Let us begin with the user interface component, index.html file:

First, we link some external CSS resources, and JavaScript files for pyodide and CodeMirror using a CDN service, cdnjs. We also include our own script file, main.js inside our body tag, since we will be using it to write page content. As UI components, we have a simple header, a textarea for code input, with an id  “code”, which will be used by CodeMirror to setup the python code-editor, and a textarea for output, with an id “output” which will be used by pyodide to display the output of the executed python code.

HTML




<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>run python in browser!</title>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
        integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
</head>
  
<body>
    <div class="container-fluid bg-light">
        <section class="header text-center p-5">
            <h2 class="text-dark">python editor with <a href="https://codemirror.net/" target="_blank">CodeMirror</a>
                and
                <a href="https://pyodide.org/en/stable/index.html" target="_blank">pyodide</a>
            </h2>
        </section>
        <div class="d-flex flex-column">
            <section class="input">
                <ul class="nav nav-tabs">
                    <li class="nav-item">
                        <a class="nav-link active" aria-current="page">
                            <h4>Input</h4>
                        </a>
                    </li>
                </ul>
                <div><textarea id="code" name="code">
                </textarea>
                </div>
            </section>
            <div class="align-self-center m-3">
                <button type="button" class="btn btn-success" onclick="evaluatePython()">
                    <h5>Run</h5>
                </button>
            </div>
            <section class="output">
                <ul class="nav nav-tabs">
                    <li class="nav-item">
                        <a class="nav-link active" aria-current="page">
                            <h4>Output</h4>
                        </a>
                    </li>
                </ul>
                <div>
                    <textarea id="output" name="output" class="w-100" rows="15">
                    </textarea>
                </div>
            </section>
        </div>
  
    </div>
        integrity="sha512-XMlgZzPyVXf1I/wbGnofk1Hfdx+zAWyZjh6c21yGo/k1zNC4Ve6xcQnTDTCHrjFGsOrVicJsBURLYktVEu/8vQ=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
        integrity="sha512-/mavDpedrvPG/0Grj2Ughxte/fsm42ZmZWWpHz1jCbzd5ECv8CB7PomGtw0NAnhHmE/lkDFkRMupjoohbKNA1Q=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src='main.js'></script>
</body>
  
</html>


Alright, now let us move on to our JavaScript file, which contains the code for CodeMirror and pyodide setup.

main.js:

We define our output element, which represents the textarea element with id “output” using document.getElementById. To initialize the editor, we make use of the method fromTextArea provided by CodeMirror, which replaces the textarea with a CodeMirror instance. The text in the textarea will provide the content for the editor which we later access using editor.getValue(). To setup the pyodide, we define an async function main(), which calls the loadPyodide method, with the indexURL as the latest version of pyodide, provided by CDN service. It sets up the Python environment and returns the Pyodide top level namespace as a promise. Now, pyodide is ready to use.

Javascript




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(`sum([1, 2, 3, 4, 5])`);
output.value = "Initializing...\n";
  
async function main() {
    let pyodide = await loadPyodide({ indexURL: "https://cdn.jsdelivr.net/pyodide/v0.18.1/full/" });
    // Pyodide ready
    output.value += "Ready!\n";
    return pyodide;
};
  
let pyodideReadyPromise = main();
  
function addToOutput(s) {
    output.value += ">>>" + s + "\n";
}
  
async function evaluatePython() {
    let pyodide = await pyodideReadyPromise;
    try {
        console.log(editor.getValue())
        let output = pyodide.runPython(editor.getValue());
        addToOutput(output);
    } catch (err) {
        addToOutput(err);
    }
}


To execute the code, we define a method evaluatePython(), which essentially calls the runPython method provided by pyodide. It takes python code as input in the form of string, and executes it, and returns the result of the expression, translated to JavaScript string. We append this string to our output, using addtoOutput() method. This output represents the final output, which was the result of executed python code. 

That is all, we have built a simple code editor which can execute python code inside the browser! As a fun little activity, you can try to build another component, Debug Output, which would display the result of all print statements inside code, as default the result is displayed in the console.

To run this application, just open the index.html inside your browser:



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads