{"id":3766,"date":"2025-05-13T07:02:29","date_gmt":"2025-05-13T07:02:29","guid":{"rendered":"https:\/\/mailitics.com\/index.php\/2025\/05\/13\/running-python-programs-in-your-browser\/"},"modified":"2025-05-13T07:02:29","modified_gmt":"2025-05-13T07:02:29","slug":"running-python-programs-in-your-browser","status":"publish","type":"post","link":"https:\/\/mailitics.com\/index.php\/2025\/05\/13\/running-python-programs-in-your-browser\/","title":{"rendered":"Running Python Programs in Your\u00a0Browser"},"content":{"rendered":"<p>    Running Python Programs in Your\u00a0Browser<br \/>\n \t<BR><br \/>\n<BR><\/BR><br \/>\n    <!-- no image --><br \/>\n \t<BR><br \/>\n<BR><\/BR><\/p>\n<div>\n<p class=\"wp-block-paragraph\"><mdspan datatext=\"el1746865029470\" class=\"mdspan-comment\">In <\/mdspan>recent years, WebAssembly (often abbreviated as WASM) has emerged as an interesting technology that extends web browsers\u2019 capabilities far beyond the traditional realms of HTML, CSS, and JavaScript.\u00a0<\/p>\n<p class=\"wp-block-paragraph\">As a <a href=\"https:\/\/towardsdatascience.com\/tag\/python\/\" title=\"Python\">Python<\/a> developer, one particularly exciting application is the ability to run Python code directly in the browser. In this article, I\u2019ll explore what WebAssembly is (and its relation to the Pyodide library), talk about its benefits and everyday use cases, and dive into some practical examples of how you can use WebAssembly to run Python programs on the web.<\/p>\n<p class=\"wp-block-paragraph\">These tools can also benefit data scientists and ML professionals. Pyodide brings a significant portion of the scientific Python stack\u00a0(NumPy, Pandas, Scikit-learn, Matplotlib, SciPy, etc.) to the browser, meaning that using familiar tools and libraries during code development is possible. It can also be useful for demonstration purposes. As you\u2019ll see in my final example, combining Python\u2019s data processing power with HTML, CSS, and JavaScript for UI, you can quickly build interactive dashboards or tools without needing a separate backend for many use cases.<\/p>\n<h4 class=\"wp-block-heading\">What is WebAssembly?<\/h4>\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/towardsdatascience.com\/tag\/webassembly\/\" title=\"Webassembly\">Webassembly<\/a> is a low-level binary instruction format designed as a portable target for compiling high-level languages, such as C, C++, Rust, and even Python. It was created to enable high-performance applications on the web without some of the pitfalls of traditional JavaScript execution, such as run-time speed. Some key aspects of WebAssembly include:<\/p>\n<ul class=\"wp-block-list\">\n<li class=\"wp-block-list-item\">\n<strong>Portability.<\/strong> WebAssembly modules run consistently across all modern browsers.<\/li>\n<li class=\"wp-block-list-item\">\n<strong>Performance.<\/strong> The binary format is compact and can be parsed quickly, which allows near-native execution speed.<\/li>\n<li class=\"wp-block-list-item\">\n<strong>Security.<\/strong> Running in a sandboxed environment, WebAssembly provides strong security guarantees.<\/li>\n<li class=\"wp-block-list-item\">\n<strong>Language Agnosticism.<\/strong> Although browsers primarily support JavaScript, WebAssembly enables developers to write code in other languages and compile it to WebAssembly (wasm).<\/li>\n<\/ul>\n<h4 class=\"wp-block-heading\">What Can WebAssembly Be Used\u00a0For?<\/h4>\n<p class=\"wp-block-paragraph\">WebAssembly has a wide array of applications. Some of the most common use cases include:-<\/p>\n<ol class=\"wp-block-list\">\n<li class=\"wp-block-list-item\">\n<strong>High-Performance Web Apps.<\/strong> WebAssembly can help applications such as games, image and video editors, and simulations achieve near-native performance.<\/li>\n<li class=\"wp-block-list-item\">\n<strong>Porting Legacy Code.<\/strong> Code written in C, C++, or Rust can be compiled into WebAssembly, allowing developers to reuse existing libraries and codebases on the web.<\/li>\n<li class=\"wp-block-list-item\">\n<strong>Multimedia Processing.<\/strong> Audio and video processing libraries benefit from webassembly\u2019s speed, enabling more complex processing tasks in real-time.<\/li>\n<li class=\"wp-block-list-item\">\n<strong>Scientific Computing.<\/strong> Heavy computations such as machine learning, data visualisation, or numerical simulations can be offloaded to WebAssembly modules.<\/li>\n<li class=\"wp-block-list-item\">\n<strong>Running Multiple Languages. <\/strong>Projects like Pyodide allow Python (and its extensive ecosystem) to be<strong> <\/strong>executed in the browser without requiring a server backend.<\/li>\n<\/ol>\n<p class=\"wp-block-paragraph\">If you frequently code in Python, that last point should make your ears prick up, so let\u2019s dive into that aspect further.<\/p>\n<h4 class=\"wp-block-heading\">Running Python on the\u00a0Web<\/h4>\n<p class=\"wp-block-paragraph\">Traditionally, Python runs on the server or in desktop applications. However, thanks to initiatives like <a href=\"https:\/\/pyodide.org\/\" rel=\"noreferrer noopener\" target=\"_blank\"><strong>Pyodide<\/strong><\/a>, Python can run in the browser via WebAssembly. Pyodide compiles the CPython interpreter code into WebAssembly, allowing you to execute Python code and use many popular third-party libraries directly in your web application.<\/p>\n<p class=\"wp-block-paragraph\">And this isn\u2019t just a gimmick. There are several advantages to doing this, including:-<\/p>\n<ul class=\"wp-block-list\">\n<li class=\"wp-block-list-item\">Using Python\u2019s extensive library ecosystem, including packages for data science (NumPy, Pandas, Matplotlib) and machine learning (Scikit-Learn, TensorFlow).<\/li>\n<li class=\"wp-block-list-item\">Enhanced responsiveness as fewer round trips to a server are required.<\/li>\n<li class=\"wp-block-list-item\">It is a simpler deployment as the entire application logic can reside in the front end.<\/li>\n<\/ul>\n<p class=\"wp-block-paragraph\">We\u2019ve mentioned Pyodide a few times already, so let\u2019s take a closer look at what exactly Pyodide is.<\/p>\n<h4 class=\"wp-block-heading\">What is\u00a0Pyodide<\/h4>\n<p class=\"wp-block-paragraph\">The idea behind Pyodide was born from the growing need to run Python code directly in the browser without relying on a traditional server-side setup. Traditionally, web applications had depended on JavaScript for client-side interactions, leaving Python confined to back-end or desktop applications. However, with the advent of WebAssembly, an opportunity arose to bridge this gap.<\/p>\n<p class=\"wp-block-paragraph\">Mozilla Research recognised the potential of this approach and set out to port CPython, the reference implementation of Python, to WebAssembly using the Emscripten toolchain. This effort was about running Python in the browser and unlocking a new world of interactive, client-side applications powered by Python\u2019s rich set of libraries for data science, numerical computing, and more.\u00a0<\/p>\n<p class=\"wp-block-paragraph\">To summarise, at its core, Pyodide is a port of CPython compiled into WebAssembly. This means that when you run Python code in the browser using Pyodide, you execute a fully functional Python interpreter optimised for the web environment.<\/p>\n<p class=\"wp-block-paragraph\">Right, it\u2019s time to look at some code.<\/p>\n<h4 class=\"wp-block-heading\">Setting up a development environment<\/h4>\n<p class=\"wp-block-paragraph\">Before we start coding, let\u2019s set up our development environment. The best practice is to create a separate Python environment where you can install any necessary software and experiment with coding, knowing that anything you do in this environment won\u2019t affect the rest of your system.<\/p>\n<p class=\"wp-block-paragraph\">I use conda for this, but you can use whatever method you know best suits you. Note that I\u2019m using Linux (WSL2 on Windows).<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">#create our test environment\n(base) $ conda create -n wasm_test python=3.12 -y\n\n# Now activate it\n(base) $ conda activate wasm_test<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Now that our environment is set up, we can install the required libraries and software.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\"># \n#\n(wasm_test) $ pip install jupyter nest-asyncio<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Now type in <code>jupyter notebook <\/code>into your command prompt. You should see a jupyter notebook open in your browser. If that doesn\u2019t happen automatically, you\u2019ll likely see a screenful of information after the <code>jupyter notebook <\/code>command. Near the bottom, there will be a URL that you should copy and paste into your browser to initiate the Jupyter Notebook.<\/p>\n<p class=\"wp-block-paragraph\">Your URL will be different to mine, but it should look something like this:-<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">http:\/\/127.0.0.1:8888\/tree?token=3b9f7bd07b6966b41b68e2350721b2d0b6f388d248cc69da<\/code><\/pre>\n<h4 class=\"wp-block-heading\">Code example 1\u200a\u2014\u200aHello World equivalent using\u00a0Pyodide<\/h4>\n<p class=\"wp-block-paragraph\">Let\u2019s start with the easiest example possible. The simplest way to include Pyodide in your HTML page is via a Content Delivery Network (CDN). We then print out the text \u201cHello World!\u201d<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-markup\">&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n  &lt;meta charset=\"UTF-8\"&gt;\n  &lt;title&gt;Hello, World! with Pyodide&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n  &lt;h1&gt;Python Hello, World!&lt;\/h1&gt;\n  &lt;button id=\"runCode\"&gt;Run Python Code&lt;\/button&gt;\n  &lt;pre id=\"result\"&gt;&lt;\/pre&gt;\n\n  &lt;script src=\"https:\/\/cdn.jsdelivr.net\/pyodide\/v0.23.4\/full\/pyodide.js\"&gt;&lt;\/script&gt;\n  &lt;script&gt;\n    async function runHelloWorld() {\n      const pyodide = await loadPyodide();\n      const output = await pyodide.runPythonAsync(`\n        print(\"Hello, World!\")\n      `);\n      document.getElementById('result').textContent = output || \"Check the console for output.\";\n    }\n    document.getElementById('runCode').addEventListener('click', runHelloWorld);\n  &lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n<p class=\"wp-block-paragraph\">I ran the above code in <a href=\"https:\/\/www.w3schools.com\/html\/tryit.asp?filename=tryhtml_headings\" target=\"_blank\" rel=\"noreferrer noopener\">W3Schools HTML TryIt<\/a> editor and got this,<\/p>\n<figure class=\"wp-block-image alignwide size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/contributor.insightmediagroup.io\/wp-content\/uploads\/2025\/05\/image-89.png?ssl=1\" alt=\"\" class=\"wp-image-603763\"><figcaption class=\"wp-element-caption\">Image by Author<\/figcaption><\/figure>\n<p class=\"has-text-align-center wp-block-paragraph\">\n<p class=\"wp-block-paragraph\">When the button is clicked, Pyodide runs the Python code that prints \u201cHello, World!\u201d. We don\u2019t see anything printed on the screen, as it is printed to the console by default. We\u2019ll fix that in our following example.<\/p>\n<h4 class=\"wp-block-heading\">Code Example 2\u200a\u2014\u200aPrinting output to the\u00a0browser<\/h4>\n<p class=\"wp-block-paragraph\">In our second example, we\u2019ll use Pyodide to run Python code in the browser that will perform a simple mathematical calculation. In this case, we will calculate the square root of 16 and output the result to the browser.\u00a0<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-markup\">&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n  &lt;meta charset=\"UTF-8\"&gt;\n  &lt;title&gt;Pyodide Example&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n  &lt;h1&gt;Running Python in the Browser with Pyodide&lt;\/h1&gt;\n  &lt;button id=\"runPython\"&gt;Run Python Code&lt;\/button&gt;\n  &lt;pre id=\"output\"&gt;&lt;\/pre&gt;\n\n  &lt;!-- Load Pyodide from the CDN --&gt;\n  &lt;script src=\"https:\/\/cdn.jsdelivr.net\/pyodide\/v0.23.4\/full\/pyodide.js\"&gt;&lt;\/script&gt;\n  &lt;script&gt;\n    async function main() {\n      \/\/ Load Pyodide\n      const pyodide = await loadPyodide();\n      document.getElementById('runPython').addEventListener('click', async () =&gt; {\n        \/\/ Run a simple Python command\n        let result = await pyodide.runPythonAsync(`\n          import math\n          math.sqrt(16)\n        `);\n        document.getElementById('output').textContent = 'Square root of 16 is: ' + result;\n      });\n    }\n    main();\n  &lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Running the above code in the W3Schools TryIT browser, I got this output.<\/p>\n<figure class=\"wp-block-image alignwide size-large\"><img data-recalc-dims=\"1\" height=\"413\" width=\"1024\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/contributor.insightmediagroup.io\/wp-content\/uploads\/2025\/05\/image-90-1024x413.png?resize=1024%2C413&#038;ssl=1\" alt=\"\" class=\"wp-image-603764\"><figcaption class=\"wp-element-caption\">Image by Author<\/figcaption><\/figure>\n<h4 class=\"wp-block-heading\">Code Example 3 \u2013 Calling Python Functions from JavaScript<\/h4>\n<p class=\"wp-block-paragraph\">Another valuable and powerful feature of using Pyodide is the ability to call Python functions from JavaScript and vice versa.\u00a0<\/p>\n<p class=\"wp-block-paragraph\">In this example, we create a Python function that performs a simple mathematical operation\u2014calculating the factorial of a number\u2014and call it from JavaScript code.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-markup\">&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n  &lt;meta charset=\"UTF-8\"&gt;\n  &lt;title&gt;Call Python from JavaScript&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n  &lt;h1&gt;Calculate the Factorial of a Number&lt;\/h1&gt;\n  &lt;input type=\"number\" id=\"numberInput\" placeholder=\"Enter a number\" \/&gt;\n  &lt;button id=\"calcFactorial\"&gt;Calculate Factorial&lt;\/button&gt;\n  &lt;pre id=\"result\"&gt;&lt;\/pre&gt;\n\n  &lt;script src=\"https:\/\/cdn.jsdelivr.net\/pyodide\/v0.23.4\/full\/pyodide.js\"&gt;&lt;\/script&gt;\n  &lt;script&gt;\n    let pyodideReadyPromise = loadPyodide();\n\n    async function calculateFactorial() {\n      const pyodide = await pyodideReadyPromise;\n      \/\/ Define a Python function for calculating factorial\n      await pyodide.runPythonAsync(`\n        def factorial(n):\n            if n == 0:\n                return 1\n            else:\n                return n * factorial(n - 1)\n      `);\n      \/\/ Get the input value from the HTML form\n      const n = Number(document.getElementById('numberInput').value);\n      \/\/ Call the Python factorial function\n      let result = pyodide.globals.get(\"factorial\")(n);\n      document.getElementById('result').textContent = `Factorial of ${n} is ${result}`;\n    }\n    \n    document.getElementById('calcFactorial').addEventListener('click', calculateFactorial);\n  &lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Here is a sample output when running on W3Schools. I won\u2019t include the code section this time, just the output.<\/p>\n<figure class=\"wp-block-image alignwide size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/contributor.insightmediagroup.io\/wp-content\/uploads\/2025\/05\/image-91.png?ssl=1\" alt=\"\" class=\"wp-image-603765\"><figcaption class=\"wp-element-caption\">Image by Author<\/figcaption><\/figure>\n<h4 class=\"wp-block-heading\">Code Example 4\u2014 Using Python Libraries, e.g.\u00a0NumPy<\/h4>\n<p class=\"wp-block-paragraph\">Python\u2019s power comes from its rich ecosystem of libraries. With Pyodide, you can import and use popular libraries like NumPy for numerical computations.\u00a0<\/p>\n<p class=\"wp-block-paragraph\">The following example demonstrates how to perform array operations using NumPy in the browser. The Numpy library is loaded using the <strong>pyodide.loadPackage<\/strong> function.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-markup\">&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n  &lt;meta charset=\"UTF-8\"&gt;\n  &lt;title&gt;NumPy in the Browser&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n  &lt;h1&gt;Matrix Multiplication with NumPy&lt;\/h1&gt;\n  &lt;button id=\"runNumPy\"&gt;Run NumPy Code&lt;\/button&gt;\n  &lt;pre id=\"numpyResult\"&gt;&lt;\/pre&gt;\n\n  &lt;script src=\"https:\/\/cdn.jsdelivr.net\/pyodide\/v0.23.4\/full\/pyodide.js\"&gt;&lt;\/script&gt;\n  &lt;script&gt;\n    async function runNumPyCode() {\n      \/\/ Load the Pyodide interpreter\n      const pyodide = await loadPyodide();\n      \n      \/\/ Load the NumPy package before using it\n      await pyodide.loadPackage(\"numpy\");\n      \n      \/\/ Run Python code to perform a matrix multiplication\n      let result = await pyodide.runPythonAsync(`\n        import numpy as np\n        A = np.array([[1, 2], [3, 4]])\n        B = np.array([[2, 0], [1, 2]])\n        C = np.matmul(A, B)\n        C.tolist()  # Convert the numpy array to a Python list for display\n      `);\n      \n      \/\/ Convert the Python result (PyProxy) to a native JavaScript object\n      \/\/ so it displays properly\n      document.getElementById('numpyResult').textContent =\n        'Matrix Multiplication Result: ' + JSON.stringify(result.toJs());\n    }\n    \n    \/\/ Set up the event listener for the button\n    document.getElementById('runNumPy').addEventListener('click', runNumPyCode);\n  &lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n<figure class=\"wp-block-image alignwide size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/contributor.insightmediagroup.io\/wp-content\/uploads\/2025\/05\/image-92.png?ssl=1\" alt=\"\" class=\"wp-image-603766\"><figcaption class=\"wp-element-caption\">Image by Author<\/figcaption><\/figure>\n<h4 class=\"wp-block-heading\">Code Example 5\u2014 Using Python libraries, e.g. matplotlib<\/h4>\n<p class=\"wp-block-paragraph\">Another powerful aspect of running Python in the browser is the ability to generate visualisations. With Pyodide, you can use GUI libraries such as Matplotlib to create plots dynamically. Here\u2019s how to generate and display a simple plot on a canvas element.<\/p>\n<p class=\"wp-block-paragraph\">In this example, we create a quadratic plot (y = x\u00b2) using Matplotlib, save the image to an in-memory buffer as a PNG, and encode it as a base64 string before displaying it.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-markup\">&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n  &lt;meta charset=\"UTF-8\"&gt;\n  &lt;title&gt;Matplotlib in the Browser&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n  &lt;h1&gt;Interactive Plot with Matplotlib&lt;\/h1&gt;\n  &lt;button id=\"plotGraph\"&gt;Generate Plot&lt;\/button&gt;\n  &lt;img id=\"plotImage\" alt=\"Plot will appear here\" \/&gt;\n\n  &lt;script src=\"https:\/\/cdn.jsdelivr.net\/pyodide\/v0.23.4\/full\/pyodide.js\"&gt;&lt;\/script&gt;\n  &lt;script&gt;\n    async function generatePlot() {\n      \/\/ Load the Pyodide interpreter\n      const pyodide = await loadPyodide();\n      \n      \/\/ Load the matplotlib package before using it\n      await pyodide.loadPackage(\"matplotlib\");\n      \n      \/\/ Run Python code that creates a plot and returns it as a base64 encoded PNG image\n      let imageBase64 = await pyodide.runPythonAsync(`\n        import matplotlib.pyplot as plt\n        import io, base64\n        \n        # Create a simple plot\n        plt.figure()\n        plt.plot([0, 1, 2, 3], [0, 1, 4, 9], marker='o')\n        plt.title(\"Quadratic Plot\")\n        plt.xlabel(\"X Axis\")\n        plt.ylabel(\"Y Axis\")\n        \n        # Save the plot to a bytes buffer\n        buf = io.BytesIO()\n        plt.savefig(buf, format='png')\n        buf.seek(0)\n        \n        # Encode the image in base64 and return it\n        base64.b64encode(buf.read()).decode('ascii')\n      `);\n      \n      \/\/ Set the src attribute of the image element to display the plot\n      document.getElementById('plotImage').src = \"data:image\/png;base64,\" + imageBase64;\n    }\n    \n    \/\/ Add event listener to the button to generate the plot\n    document.getElementById('plotGraph').addEventListener('click', generatePlot);\n  &lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n<figure class=\"wp-block-image alignwide size-large\"><img data-recalc-dims=\"1\" height=\"501\" width=\"1024\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/contributor.insightmediagroup.io\/wp-content\/uploads\/2025\/05\/image-93-1024x501.png?resize=1024%2C501&#038;ssl=1\" alt=\"\" class=\"wp-image-603767\"><figcaption class=\"wp-element-caption\">Image by Author<\/figcaption><\/figure>\n<h4 class=\"wp-block-heading\">Code Example 6: Running Python in a Web\u00a0Worker<\/h4>\n<p class=\"wp-block-paragraph\">For more complex applications or when you need to ensure that heavy computations do not block the main UI thread, you can run Pyodide in a <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Web_Workers_API\" rel=\"noreferrer noopener\" target=\"_blank\">Web Worker<\/a>. Web Workers allow you to run scripts in background threads, keeping your application responsive.<\/p>\n<p class=\"wp-block-paragraph\">Below is an example of how to set up Pyodide in a Web Worker. We perform a calculation and simulate the calculation running for a while by introducing delays using the <strong>sleep()<\/strong> function. We also display a continuously updating counter showing the main UI running and responding normally.\u00a0<\/p>\n<p class=\"wp-block-paragraph\">We\u2019ll need three files for this:- an index.html file and two JavaScript files.<\/p>\n<p class=\"wp-block-paragraph\"><strong>index.html<\/strong><\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-markup\">&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n  &lt;meta charset=\"UTF-8\"&gt;\n  &lt;title&gt;Pyodide Web Worker Example&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n  &lt;h1&gt;Running Python in a Web Worker&lt;\/h1&gt;\n  &lt;button id=\"startWorker\"&gt;Start Computation&lt;\/button&gt;\n  &lt;p id=\"status\"&gt;Status: Idle&lt;\/p&gt;\n  &lt;pre id=\"workerOutput\"&gt;&lt;\/pre&gt;\n  &lt;script src=\"main.js\"&gt;&lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n<p class=\"wp-block-paragraph\"><strong>worker.js<\/strong><\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-javascript\">\/\/ Load Pyodide from the CDN inside the worker\nself.importScripts(\"https:\/\/cdn.jsdelivr.net\/pyodide\/v0.23.4\/full\/pyodide.js\");\n\nasync function initPyodide() {\n  self.pyodide = await loadPyodide();\n  \/\/ Inform the main thread that Pyodide has been loaded\n  self.postMessage(\"Pyodide loaded in Worker\");\n}\n\ninitPyodide();\n\n\/\/ Listen for messages from the main thread\nself.onmessage = async (event) =&gt; {\n  if (event.data === 'start') {\n    \/\/ Execute a heavy computation in Python within the worker.\n    \/\/ The compute function now pauses for 0.5 seconds every 1,000,000 iterations.\n    let result = await self.pyodide.runPythonAsync(`\nimport time\ndef compute():\n    total = 0\n    for i in range(1, 10000001):  # Loop from 1 to 10,000,000\n        total += i\n        if i % 1000000 == 0:\n            time.sleep(0.5)  # Pause for 0.5 seconds every 1,000,000 iterations\n    return total\ncompute()\n    `);\n    \/\/ Send the computed result back to the main thread\n    self.postMessage(\"Computed result: \" + result);\n  }\n};<\/code><\/pre>\n<p class=\"wp-block-paragraph\"><strong>main.js<\/strong><\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-javascript\">\/\/ Create a new worker from worker.js\nconst worker = new Worker('worker.js');\n\n\/\/ DOM elements to update status and output\nconst statusElement = document.getElementById('status');\nconst outputElement = document.getElementById('workerOutput');\nconst startButton = document.getElementById('startWorker');\n\nlet timerInterval;\nlet secondsElapsed = 0;\n\n\/\/ Listen for messages from the worker\nworker.onmessage = (event) =&gt; {\n  \/\/ Append any message from the worker to the output\n  outputElement.textContent += event.data + \"n\";\n\n  if (event.data.startsWith(\"Computed result:\")) {\n    \/\/ When computation is complete, stop the timer and update status\n    clearInterval(timerInterval);\n    statusElement.textContent = `Status: Completed in ${secondsElapsed} seconds`;\n  } else if (event.data === \"Pyodide loaded in Worker\") {\n    \/\/ Update status when the worker is ready\n    statusElement.textContent = \"Status: Worker Ready\";\n  }\n};\n\n\/\/ When the start button is clicked, begin the computation\nstartButton.addEventListener('click', () =&gt; {\n  \/\/ Reset the display and timer\n  outputElement.textContent = \"\";\n  secondsElapsed = 0;\n  statusElement.textContent = \"Status: Running...\";\n  \n  \/\/ Start a timer that updates the main page every second\n  timerInterval = setInterval(() =&gt; {\n    secondsElapsed++;\n    statusElement.textContent = `Status: Running... ${secondsElapsed} seconds elapsed`;\n  }, 1000);\n  \n  \/\/ Tell the worker to start the heavy computation\n  worker.postMessage('start');\n});<\/code><\/pre>\n<p class=\"wp-block-paragraph\">To run this code, create all three files above and put them into the same directory on your local system. In that directory, type in the following command.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">$ python -m http.server 8000<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Now, in your browser, type this URL into it.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-markup\">http:\/\/localhost:8000\/index.html<\/code><\/pre>\n<p class=\"wp-block-paragraph\">You should see a screen like this.<\/p>\n<figure class=\"wp-block-image alignwide size-large\"><img data-recalc-dims=\"1\" height=\"490\" width=\"1024\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/contributor.insightmediagroup.io\/wp-content\/uploads\/2025\/05\/image-98-1024x490.png?resize=1024%2C490&#038;ssl=1\" alt=\"\" class=\"wp-image-603786\"><figcaption class=\"wp-element-caption\">Image by Author<\/figcaption><\/figure>\n<p class=\"wp-block-paragraph\">Now, if you press the <code>&lt;strong&gt;Start Computation&lt;\/strong&gt;<\/code> button, you should see a counter displayed on the screen, starting at 1 and ticking up by 1 every second until the computation is complete and its final result is displayed\u200a\u2014\u200aabout 5 seconds in total.\u00a0<\/p>\n<p class=\"wp-block-paragraph\">This shows that the front-end logic and computation are not constrained by the work that\u2019s being done by the Python code behind the button.\u00a0<\/p>\n<figure class=\"wp-block-image alignwide size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/contributor.insightmediagroup.io\/wp-content\/uploads\/2025\/05\/image-99.png?ssl=1\" alt=\"\" class=\"wp-image-603787\"><figcaption class=\"wp-element-caption\">Image by Author<\/figcaption><\/figure>\n<h4 class=\"wp-block-heading\">Code Example 7: Running a simple data dashboard<\/h4>\n<p class=\"wp-block-paragraph\">For our final example, I\u2019ll show you how to run a simple data dashboard directly in your browser. Our source data will be synthetic sales data in a CSV file.<\/p>\n<p class=\"wp-block-paragraph\">We need three files for this, all of which should be in the same folder.<\/p>\n<p class=\"wp-block-paragraph\"><strong>sales_data.csv<\/strong><\/p>\n<p class=\"wp-block-paragraph\">The file I used had 100,000 records, but you can make this file as big or small as you like. Here are the first twenty records to give you an idea of what the data looked like.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">Date,Category,Region,Sales\n2021-01-01,Books,West,610.57\n2021-01-01,Beauty,West,2319.0\n2021-01-01,Electronics,North,4196.76\n2021-01-01,Electronics,West,1132.53\n2021-01-01,Home,North,544.12\n2021-01-01,Beauty,East,3243.56\n2021-01-01,Sports,East,2023.08\n2021-01-01,Fashion,East,2540.87\n2021-01-01,Automotive,South,953.05\n2021-01-01,Electronics,North,3142.8\n2021-01-01,Books,East,2319.27\n2021-01-01,Sports,East,4385.25\n2021-01-01,Beauty,North,2179.01\n2021-01-01,Fashion,North,2234.61\n2021-01-01,Beauty,South,4338.5\n2021-01-01,Beauty,East,783.36\n2021-01-01,Sports,West,696.25\n2021-01-01,Electronics,South,97.03\n2021-01-01,Books,West,4889.65<\/code><\/pre>\n<p class=\"wp-block-paragraph\"><strong>index.html<\/strong><\/p>\n<p class=\"wp-block-paragraph\">This is the main GUI interface to our dashboard.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-markup\">&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n    &lt;meta charset=\"UTF-8\"&gt;\n    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;\n    &lt;title&gt;Pyodide Sales Dashboard&lt;\/title&gt;\n    &lt;style&gt;\n        body { font-family: Arial, sans-serif; text-align: center; padding: 20px; }\n        h1 { color: #333; }\n        input { margin: 10px; }\n        select, button { padding: 10px; font-size: 16px; margin: 5px; }\n        img { max-width: 100%; display: block; margin: 20px auto; }\n        table { width: 100%; border-collapse: collapse; margin-top: 20px; }\n        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }\n\n        th { background-color: #f4f4f4; }\n  .sortable th {\n   cursor: pointer;\n   user-select: none;\n  }\n  .sortable th:hover {\n   background-color: #e0e0e0;\n  }\n    &lt;\/style&gt;\n    &lt;script src=\"https:\/\/cdn.jsdelivr.net\/pyodide\/v0.23.4\/full\/pyodide.js\"&gt;&lt;\/script&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n\n    &lt;h1&gt;<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f4ca.png?ssl=1\" alt=\"\ud83d\udcca\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> Pyodide Sales Dashboard&lt;\/h1&gt;\n\n    &lt;input type=\"file\" id=\"csvUpload\" accept=\".csv\"&gt;\n    \n    &lt;label for=\"metricSelect\"&gt;Select Sales Metric:&lt;\/label&gt;\n    &lt;select id=\"metricSelect\"&gt;\n        &lt;option value=\"total_sales\"&gt;Total Sales&lt;\/option&gt;\n        &lt;option value=\"category_sales\"&gt;Sales by Category&lt;\/option&gt;\n        &lt;option value=\"region_sales\"&gt;Sales by Region&lt;\/option&gt;\n        &lt;option value=\"monthly_trends\"&gt;Monthly Trends&lt;\/option&gt;\n    &lt;\/select&gt;\n\n    &lt;br&gt;&lt;br&gt;\n    &lt;button id=\"analyzeData\"&gt;Analyze Data&lt;\/button&gt;\n\n    &lt;h2&gt;<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f4c8.png?ssl=1\" alt=\"\ud83d\udcc8\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> Sales Data Visualization&lt;\/h2&gt;\n    &lt;img id=\"chartImage\" alt=\"Generated Chart\" style=\"display: none\"&gt;\n    &lt;h2&gt;<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f4ca.png?ssl=1\" alt=\"\ud83d\udcca\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> Sales Data Table&lt;\/h2&gt;\n    &lt;div id=\"tableOutput\"&gt;&lt;\/div&gt;\n\n    &lt;script src=\"main.js\"&gt;&lt;\/script&gt;\n\n&lt;\/script&gt;\n\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n<p class=\"wp-block-paragraph\"><strong>main.js<\/strong><\/p>\n<p class=\"wp-block-paragraph\">This contains our main Python pyodide code.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">async function loadPyodideAndRun() {\n  const pyodide = await loadPyodide();\n  await pyodide.loadPackage([\"numpy\", \"pandas\", \"matplotlib\"]);\n  \n  document.getElementById(\"analyzeData\").addEventListener(\"click\", async () =&gt; {\n    const fileInput = document.getElementById(\"csvUpload\");\n    const selectedMetric = document.getElementById(\"metricSelect\").value;\n    const chartImage = document.getElementById(\"chartImage\");\n    const tableOutput = document.getElementById(\"tableOutput\");\n    \n    if (fileInput.files.length === 0) {\n      alert(\"Please upload a CSV file first.\");\n      return;\n    }\n\n    \/\/ Read the CSV file\n    const file = fileInput.files[0];\n    const reader = new FileReader();\n    reader.readAsText(file);\n    \n    reader.onload = async function (event) {\n      const csvData = event.target.result;\n      \n      await pyodide.globals.set('csv_data', csvData);\n      await pyodide.globals.set('selected_metric', selectedMetric);\n      \n      const pythonCode = \n        'import sysn' +\n        'import ion' +\n        'import numpy as npn' +\n        'import pandas as pdn' +\n        'import matplotlibn' +\n        'matplotlib.use(\"Agg\")n' +\n        'import matplotlib.pyplot as pltn' +\n        'import base64n' +\n        'n' +\n        '# Capture outputn' +\n        'output_buffer = io.StringIO()n' +\n        'sys.stdout = output_buffern' +\n        'n' +\n        '# Read CSV directly using csv_data from JavaScriptn' +\n        'df = pd.read_csv(io.StringIO(csv_data))n' +\n        'n' +\n        '# Ensure required columns existn' +\n        'expected_cols = {\"Date\", \"Category\", \"Region\", \"Sales\"}n' +\n        'if not expected_cols.issubset(set(df.columns)):n' +\n        '    print(\"<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/274c.png?ssl=1\" alt=\"\u274c\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> CSV must contain 'Date', 'Category', 'Region', and 'Sales' columns.\")n' +\n        '    sys.stdout = sys.__stdout__n' +\n        '    exit()n' +\n        'n' +\n        '# Convert Date column to datetimen' +\n        'df[\"Date\"] = pd.to_datetime(df[\"Date\"])n' +\n        'n' +\n        'plt.figure(figsize=(12, 6))n' +\n        'n' +\n        'if selected_metric == \"total_sales\":n' +\n        '    total_sales = df[\"Sales\"].sum()n' +\n        '    print(f\"<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f4b0.png?ssl=1\" alt=\"\ud83d\udcb0\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> Total Sales: ${total_sales:,.2f}\")n' +\n        '    # Add daily sales trend for total sales viewn' +\n        '    daily_sales = df.groupby(\"Date\")[\"Sales\"].sum().reset_index()n' +\n        '    plt.plot(daily_sales[\"Date\"], daily_sales[\"Sales\"], marker=\"o\")n' +\n        '    plt.title(\"Daily Sales Trend\")n' +\n        '    plt.ylabel(\"Sales ($)\")n' +\n        '    plt.xlabel(\"Date\")n' +\n        '    plt.xticks(rotation=45)n' +\n        '    plt.grid(True, linestyle=\"--\", alpha=0.7)n' +\n        '    # Show top sales days in tablen' +\n        '    table_data = daily_sales.sort_values(\"Sales\", ascending=False).head(10)n' +\n        '    table_data[\"Sales\"] = table_data[\"Sales\"].apply(lambda x: f\"${x:,.2f}\")n' +\n        '    print(\"&lt;h3&gt;Top 10 Sales Days&lt;\/h3&gt;\")n' +\n        '    print(table_data.to_html(index=False))n' +\n        'elif selected_metric == \"category_sales\":n' +\n        '    category_sales = df.groupby(\"Category\")[\"Sales\"].agg([n' +\n        '        (\"Total Sales\", \"sum\"),n' +\n        '        (\"Average Sale\", \"mean\"),n' +\n        '        (\"Number of Sales\", \"count\")n' +\n        '    ]).sort_values(\"Total Sales\", ascending=True)n' +\n        '    category_sales[\"Total Sales\"].plot(kind=\"bar\", title=\"Sales by Category\")n' +\n        '    plt.ylabel(\"Sales ($)\")n' +\n        '    plt.xlabel(\"Category\")n' +\n        '    plt.grid(True, linestyle=\"--\", alpha=0.7)n' +\n        '    # Format table datan' +\n        '    table_data = category_sales.copy()n' +\n        '    table_data[\"Total Sales\"] = table_data[\"Total Sales\"].apply(lambda x: f\"${x:,.2f}\")n' +\n        '    table_data[\"Average Sale\"] = table_data[\"Average Sale\"].apply(lambda x: f\"${x:,.2f}\")n' +\n        '    print(\"&lt;h3&gt;Sales by Category&lt;\/h3&gt;\")n' +\n        '    print(table_data.to_html())n' +\n        'elif selected_metric == \"region_sales\":n' +\n        '    region_sales = df.groupby(\"Region\")[\"Sales\"].agg([n' +\n        '        (\"Total Sales\", \"sum\"),n' +\n        '        (\"Average Sale\", \"mean\"),n' +\n        '        (\"Number of Sales\", \"count\")n' +\n        '    ]).sort_values(\"Total Sales\", ascending=True)n' +\n        '    region_sales[\"Total Sales\"].plot(kind=\"barh\", title=\"Sales by Region\")n' +\n        '    plt.xlabel(\"Sales ($)\")n' +\n        '    plt.ylabel(\"Region\")n' +\n        '    plt.grid(True, linestyle=\"--\", alpha=0.7)n' +\n        '    # Format table datan' +\n        '    table_data = region_sales.copy()n' +\n        '    table_data[\"Total Sales\"] = table_data[\"Total Sales\"].apply(lambda x: f\"${x:,.2f}\")n' +\n        '    table_data[\"Average Sale\"] = table_data[\"Average Sale\"].apply(lambda x: f\"${x:,.2f}\")n' +\n        '    print(\"&lt;h3&gt;Sales by Region&lt;\/h3&gt;\")n' +\n        '    print(table_data.to_html())n' +\n        'elif selected_metric == \"monthly_trends\":n' +\n        '    df[\"Month\"] = df[\"Date\"].dt.to_period(\"M\")n' +\n        '    monthly_sales = df.groupby(\"Month\")[\"Sales\"].agg([n' +\n        '        (\"Total Sales\", \"sum\"),n' +\n        '        (\"Average Sale\", \"mean\"),n' +\n        '        (\"Number of Sales\", \"count\")n' +\n        '    ])n' +\n        '    monthly_sales[\"Total Sales\"].plot(kind=\"line\", marker=\"o\", title=\"Monthly Sales Trends\")n' +\n        '    plt.ylabel(\"Sales ($)\")n' +\n        '    plt.xlabel(\"Month\")n' +\n        '    plt.xticks(rotation=45)n' +\n        '    plt.grid(True, linestyle=\"--\", alpha=0.7)n' +\n        '    # Format table datan' +\n        '    table_data = monthly_sales.copy()n' +\n        '    table_data[\"Total Sales\"] = table_data[\"Total Sales\"].apply(lambda x: f\"${x:,.2f}\")n' +\n        '    table_data[\"Average Sale\"] = table_data[\"Average Sale\"].apply(lambda x: f\"${x:,.2f}\")n' +\n        '    print(\"&lt;h3&gt;Monthly Sales Analysis&lt;\/h3&gt;\")n' +\n        '    print(table_data.to_html())n' +\n        'n' +\n        'plt.tight_layout()n' +\n        'n' +\n        'buf = io.BytesIO()n' +\n        'plt.savefig(buf, format=\"png\", dpi=100, bbox_inches=\"tight\")n' +\n        'plt.close()n' +\n        'img_data = base64.b64encode(buf.getvalue()).decode(\"utf-8\")n' +\n        'print(f\"IMAGE_START{img_data}IMAGE_END\")n' +\n        'n' +\n        'sys.stdout = sys.__stdout__n' +\n        'output_buffer.getvalue()';\n\n      const result = await pyodide.runPythonAsync(pythonCode);\n      \n      \/\/ Extract and display output with markers\n      const imageMatch = result.match(\/IMAGE_START(.+?)IMAGE_END\/);\n      if (imageMatch) {\n        const imageData = imageMatch[1];\n        chartImage.src = 'data:image\/png;base64,' + imageData;\n        chartImage.style.display = 'block';\n        \/\/ Remove the image data from the result before showing the table\n        tableOutput.innerHTML = result.replace(\/IMAGE_START(.+?)IMAGE_END\/, '').trim();\n      } else {\n        chartImage.style.display = 'none';\n        tableOutput.innerHTML = result.trim();\n      }\n    };\n  });\n}\n\nloadPyodideAndRun();<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Like the previous example, you can run this as follows. Create all three files and place them in the same directory on your local system. In that directory, on a command terminal, type in the following,<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">$ python -m http.server 8000<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Now, in your browser, type this URL into it.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-markup\">http:\/\/localhost:8000\/index.html<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Initially, your screen should look like this,<\/p>\n<figure class=\"wp-block-image alignwide size-large\"><img data-recalc-dims=\"1\" height=\"502\" width=\"1024\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/contributor.insightmediagroup.io\/wp-content\/uploads\/2025\/05\/image-100-1024x502.png?resize=1024%2C502&#038;ssl=1\" alt=\"\" class=\"wp-image-603788\"><figcaption class=\"wp-element-caption\">Image by Author<\/figcaption><\/figure>\n<p class=\"wp-block-paragraph\">Click on the <code>&lt;strong&gt;Choose File&lt;\/strong&gt;<\/code> button and select the data file you created to input into your dashboard. After that, choose a suitable metric from the <code>&lt;strong&gt;Select Sales Metric&lt;\/strong&gt;<\/code> dropdown list and click the <code>&lt;strong&gt;Analyze data&lt;\/strong&gt;<\/code> button. Depending on what options you choose to display, you should see something like this on your screen.<\/p>\n<figure class=\"wp-block-image alignwide size-large\"><img data-recalc-dims=\"1\" height=\"484\" width=\"1024\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/contributor.insightmediagroup.io\/wp-content\/uploads\/2025\/05\/wsm2-fotor-20250509165235-2-1024x484.png?resize=1024%2C484&#038;ssl=1\" alt=\"\" class=\"wp-image-603790\"><figcaption class=\"wp-element-caption\">Image by Author<\/figcaption><\/figure>\n<h4 class=\"wp-block-heading\">Summary<\/h4>\n<p class=\"wp-block-paragraph\">In this article, I described how using Pyodide and WebAssembly, we can run Python programs inside our browsers and showed several examples that demonstrate this. I talked about WebAssembly\u2019s role as a portable, high-performance compilation target that extends browser capabilities and how this is realised in the Python ecosystem using the third-party library Pyodide.<\/p>\n<p class=\"wp-block-paragraph\">To illustrate the power and versatility of Pyodide, I provided several examples of its use, including:-<\/p>\n<ul class=\"wp-block-list\">\n<li class=\"wp-block-list-item\">A basic \u201cHello, World!\u201d example.<\/li>\n<li class=\"wp-block-list-item\">Calling Python functions from JavaScript.<\/li>\n<li class=\"wp-block-list-item\">Utilising NumPy for numerical operations.<\/li>\n<li class=\"wp-block-list-item\">Generating visualisations with Matplotlib.<\/li>\n<li class=\"wp-block-list-item\">Running computationally heavy Python code in a Web Worker.<\/li>\n<li class=\"wp-block-list-item\">A data dashboard<\/li>\n<\/ul>\n<p class=\"wp-block-paragraph\">I hope that after reading this article, you will, like me, realise just how powerful a combination of Python, Pyodide, and a web browser can be.<\/p>\n<p>The post <a href=\"https:\/\/towardsdatascience.com\/running-python-programs-in-your-browser\/\">Running Python Programs in Your\u00a0Browser<\/a> appeared first on <a href=\"https:\/\/towardsdatascience.com\/\">Towards Data Science<\/a>.<\/p>\n<\/div>\n<p> \t<BR><br \/>\n <BR><\/BR><br \/>\n    Thomas Reid<br \/>\n \t<BR><br \/>\n<BR><\/BR><br \/>\n<a href=\"https:\/\/towardsdatascience.com\/running-python-programs-in-your-browser\/\">Go to original source<\/a><br \/>\n \t<BR><br \/>\n <BR><\/BR><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Running Python Programs in Your\u00a0Browser In recent years, WebAssembly (often abbreviated as WASM) has emerged as an interesting technology that extends web browsers\u2019 capabilities far beyond the traditional realms of HTML, CSS, and JavaScript.\u00a0 As a Python developer, one particularly exciting application is the ability to run Python code directly in the browser. In this [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[62,401,67,160,157,280,2649],"tags":[2651,102,2650],"class_list":["post-3766","post","type-post","status-publish","format-standard","hentry","category-aimldsaimlds","category-data-engineering","category-deep-dives","category-programming","category-python","category-technology","category-webassembly","tag-browser","tag-python","tag-webassembly"],"_links":{"self":[{"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/posts\/3766"}],"collection":[{"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/comments?post=3766"}],"version-history":[{"count":0,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/posts\/3766\/revisions"}],"wp:attachment":[{"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/media?parent=3766"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/categories?post=3766"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/tags?post=3766"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}