Build Python code editor using CodeMirror and pyodide - GeeksforGeeks

22 Nov, 2021
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. 
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'>    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"        integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.4/codemirror.min.css" />    <script src="https://cdn.jsdelivr.net/pyodide/v0.18.1/full/pyodide.js"></script></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>    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.63.3/codemirror.min.js"        integrity="sha512-XMlgZzPyVXf1I/wbGnofk1Hfdx+zAWyZjh6c21yGo/k1zNC4Ve6xcQnTDTCHrjFGsOrVicJsBURLYktVEu/8vQ=="        crossorigin="anonymous" referrerpolicy="no-referrer"></script>    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.63.3/mode/python/python.min.js"        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:
Python
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
How to Install PIP on Windows ?
How to drop one or multiple columns in Pandas Dataframe
How To Convert Python Dictionary To JSON?
Check if element exists in list in Python
Python | Pandas dataframe.groupby()
Python | Get unique values from a list
Defaultdict in Python
Python | os.path.join() method
Python Classes and Objects
Create a directory in Python