You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Pyodide与Web Worker在浏览器中获取Python执行结果字符串

解决Pyodide Worker捕获Python输出并返回的问题

问题核心是当前代码仅返回执行状态提示,未捕获Python代码中print等输出到标准流的内容。需要通过重定向Pyodide的stdout/stderr来收集输出,再返回给主线程。

修改worker.js代码

这是关键修改点,需要在Pyodide中捕获标准输出和错误:

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/",
    });
    // 初始化输出收集器
    self.outputBuffer = [];
    // 重定向stdout
    self.pyodide.setStdout({
        write: (text) => {
            self.outputBuffer.push(text);
        },
        flush: () => {}
    });
    // 重定向stderr
    self.pyodide.setStderr({
        write: (text) => {
            self.outputBuffer.push(`[ERROR] ${text}`);
        },
        flush: () => {}
    });
    // await self.pyodide.loadPackage(["numpy"]);
}

let pyodideReadyPromise = loadPyodideAndPackages();

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

    // 清空之前的输出缓存
    self.outputBuffer = [];

    // 将上下文变量注入到Pyodide的Python环境
    for (const key in context) {
        self.pyodide.globals.set(key, context[key]);
    }

    try {
        // 运行Python代码
        await self.pyodide.runPythonAsync(pythonCode);
        // 将收集到的输出拼接成字符串返回
        const output = self.outputBuffer.join("");
        postMessage({ id, result: output || "Execution complete" });
    } catch (error) {
        // 捕获异常时,也带上已收集的输出
        const output = self.outputBuffer.join("");
        const errorMsg = output ? `${output}\n[EXCEPTION] ${error.message}` : error.message;
        postMessage({ id, error: errorMsg });
    }
};

可选微调main-worker.js

如果需要处理空结果的情况,可在runPythonCode中增加默认返回逻辑:

// main-worker.js
async function runPythonCode(pythonCode, context) {
    try {
        const { result, error } = await asyncRun(pythonCode, context);
        if (result) {
            return result.toString()
        } else if (error) {
            return error
        }
        // 添加无输出时的默认返回
        return "No output generated"
    } catch (e) {
        console.error("Error communicating with the worker:", e);
        return `Worker communication error: ${e.message}`;
    }
}

测试与使用

修改后,运行print('Hello, World!')时,result变量会拿到字符串Hello, World!\n,你可以将其插入到目标div中:

// test-code中更新点击事件逻辑
$(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)
          // 将结果插入到指定div
          $(element).find(".result-display").text(result);
       }
   )

关键说明

  • 通过pyodide.setStdout和pyodide.setStderr可以捕获Python代码的所有标准输出和错误输出。
  • 每次运行代码前清空输出缓存,避免不同运行的输出混在一起。
  • 异常处理时同时返回已收集的输出和异常信息,便于调试。

内容的提问来源于stack exchange,提问作者inquilabee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 06:11:18