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

如何基于Web Workers与Pyodide实现Python代码执行时逐行输出?

解决Pyodide在Web Worker中实时逐行输出的问题

你的问题出在Pyodide的batched回调机制上——这个回调会累积输出内容,直到缓冲区满或者代码执行结束才会触发,所以没法实现实时逐行输出。要改成实时输出,需要改用write回调,它会在每次有输出内容时立即触发。

以下是修改后的完整代码:

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

async function loadPyodideAndPackages() {
  self.pyodide = await loadPyodide({
    indexURL: "https://cdn.jsdelivr.net/pyodide/v0.26.1/full/",
  });
  await self.pyodide.loadPackage(["numpy", "pytz"]);
  self.postMessage({ status: "READY" });
}

let pyodideReadyPromise = loadPyodideAndPackages();

self.onmessage = async (event) => {
  await pyodideReadyPromise;

  // 每次执行前重置输出回调,避免残留影响
  self.pyodide.setStdout({
    write: (str) => {
      // 实时发送输出内容到主线程
      self.postMessage({ line: str });
    },
  });

  self.pyodide.setStderr({
    write: (str) => {
      self.postMessage({ error: str });
    },
  });

  try {
    await self.pyodide.runPythonAsync(event.data);
    self.postMessage({ status: "done" });
  } catch (error) {
    self.postMessage({ error: error.message });
  }
};

关键改动说明:

  • 将batched回调替换为write:write会在每有输出内容时立即调用,不管内容多少,实现实时输出。
  • 移除了stdout和stderr的数组存储(如果不需要事后汇总输出的话),如果需要保留可以继续添加。
  • 每次处理新的代码执行请求时重新设置输出回调,确保不会和之前的执行产生干扰。

另外,如果你的Python代码中使用print但输出没有即时触发,可以在print后手动调用flush=True,比如print("内容", flush=True),这样Python会立即刷新输出缓冲区,让write回调马上拿到内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 01:26:14