如何基于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
相关产品推荐
相关产品推荐

