Uncategorized

javascript – Run python and get result as string in browser


I want to run Python code from a text-area in HTML and save the output in a div. I am using pyodide.js https://cdn.jsdelivr.net/pyodide/v0.25.0/full/pyodide.js to run Python. I would also like to use a worker which does not affect the main JS thread.

I have a working code that logs the output to the JavaScript console in the browser, and I can’t figure out a way to get the result in a string.

Can you help me get the code output saved to a variable?

The main function runPythonCode outputs the result to the console instead of returning an output to the variable result (result=undefined) in main-worker.js.

Find the detailed code below.

//test-code
import { runPythonCode } from "./main-worker.js";

$(element).find(".run-code:first").click(
     async function() {
          let current_code = "print('Hello, World!')"
                        
          let result = await runPythonCode(current_code)

          console.log("Run clicked", result)
       }
   )

// main-worker.js

// main-worker.js

import { asyncRun } from "./py-worker.js";

console.log("Python main worker started.")

async function runPythonCode(pythonCode, context) {
    try {
        const { result, error } = await asyncRun(pythonCode, context);
        if (result) {
            return result.toString()
        } else if (error) {
            return error
        }
    } catch (e) {
        console.error("Error communicating with the worker:", e);
    }
}

export {runPythonCode}

// py-worker.js

// py-worker.js

const pyodideWorker = new Worker("./worker.js");

const callbacks = {};

pyodideWorker.onmessage = (event) => {
    const { id, result, error } = event.data;
    const onSuccess = callbacks[id];
    delete callbacks[id];

    if (onSuccess) {
        if (result) {
            onSuccess({ result });
        } else if (error) {
            onSuccess({ error });
        }
    }
};

const asyncRun = (pythonCode, context = {}) => {
    const id = Date.now().toString(); // Unique identifier for each run
    return new Promise((resolve) => {
        callbacks[id] = resolve;
        pyodideWorker.postMessage({ id, pythonCode, context });
    });
};

export { asyncRun };

// worker.js

// worker.js

importScripts("https://cdn.jsdelivr.net/pyodide/v0.25.0/full/pyodide.js");

async function loadPyodideAndPackages() {
    self.pyodide = await loadPyodide({
        "indexURL" : "https://cdn.jsdelivr.net/pyodide/v0.25.0/full/",
    });
    // Add any necessary packages here
    // await self.pyodide.loadPackage(["numpy"]);
}

let pyodideReadyPromise = loadPyodideAndPackages();

self.onmessage = async (event) => {
    await pyodideReadyPromise;
    const { id, pythonCode, context } = event.data;

    // Copy the context variables to the worker's scope
    for (const key in context) {
        self[key] = context[key];
    }

    try {
        // Load packages and run Python code
        await self.pyodide.runPythonAsync(pythonCode);
        postMessage({ id, result: "Execution complete" });
    } catch (error) {
        postMessage({ id, error: error.message });
    }
};



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *