资讯动态

Cherry Studio 代码执行架构:Pyodide Web Worker 中运行 Python 代码块的全链路解析

发布时间:2026/9/20 14:43:33 来源:尧图企业网站定制
人工智能大模型AI 应用交互助手本地部署【免费下载链接】cherry-studio Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端项目地址https://gitcode.com/CherryHQ/cherry-studio点击查看免费下载Cherry Studio 允许用户在聊天消息的 Python 围栏代码块上点击运行借助 Pyodide 在渲染进程renderer内部直接执行 Python 代码。本文基于仓库 code-execution.md 文档结合CodeBlockView、PyodideService与pyodide.worker的源码实现完整讲解该功能的激活条件、运行链路、Worker 行为、输出与失败语义、安全边界及验证方式读完后你将掌握如何配置、调用、排查并扩展这条代码执行链路。功能概览与激活条件Python 围栏代码块可以在渲染进程中通过 Pyodide 直接运行执行过程发生在 Web Worker 中因此加载 Python 包与运行 Python 代码都不会阻塞 React UI 线程用户界面保持流畅响应。代码块的运行工具由 CodeBlockView.tsx 暴露只有在以下两个条件同时成立时才显示代码块语言为python偏好设置chat.code.execution.enabled为true。对应的实现位于isExecutable计算属性CodeBlockView.tsxconst isExecutable useMemo(() { return allowExecution codeExecutionEnabled language python }, [allowExecution, codeExecutionEnabled, language])其中allowExecution是组件 props 传入的执行许可默认truecodeExecutionEnabled来自偏好读取const [codeExecutionEnabled] usePreference(chat.code.execution.enabled) const [codeExecutionTimeoutMinutes] usePreference(chat.code.execution.timeout_minutes)偏好配置项与默认值这两个偏好项在 preferenceSchemas.ts 中定义类型为boolean与numberL127-L130默认值分别为配置键类型默认值说明chat.code.execution.enabledbooleanfalse是否允许在代码块上显示运行工具默认关闭chat.code.execution.timeout_minutesnumber1单次执行超时时间分钟默认 1 分钟默认值可在 preferenceSchemas.ts 中确认chat.code.execution.enabled: false、chat.code.execution.timeout_minutes: 1。超时分钟后点击运行handleRunScript会以毫秒为单位把超时传入服务层pyodideService .runScript(source, {}, codeExecutionTimeoutMinutes * 60000) .then((result) setExecutionResult(result)) ...注意此处调用时传入的context是空对象{}source取自latestActionContextRef它始终持有 workbench 中的最新源码代码块处于编辑态时也能运行最新内容。返回的{ text, image? }会渲染在代码面下方的StatusBar中CodeBlockView.tsximage存在时通过ImageViewer展示。运行时全链路一次点击运行的完整数据流如下CodeBlockView → PyodideService.runScript → initialize one shared pyodide.worker → postMessage({ id, python, context }) → loadPackagesFromImports(python) → runPythonAsync(python) → postMessage({ id, output }) → formatOutput(output) → StatusBar text and optional imagePyodideService请求编排层PyodideService.ts 是这条链路的编排核心负责 worker 初始化、请求 ID 管理、响应 resolver、超时、重置与终止。其单例pyodideService在整个渲染进程内共享配置常量如下const SERVICE_CONFIG { WORKER: { MAX_INIT_RETRY: 5, // 最大初始化重试次数 REQUEST_TIMEOUT: { INIT: 30000, // 30 秒初始化超时 RUN: 60000 // 60 秒默认运行超时 } } }共享初始化与重试机制initialize()通过initPromise保证多个调用共享同一次初始化worker 创建后由专门的initHandler监听initialized/init-error消息30 秒内未完成初始化即判定超时并重试最多重试 5 次MAX_INIT_RETRY。初始化失败会以可读文本返回给 UI而不是抛出未处理异常。请求与响应配对每次runScript生成一个uuid作为请求 ID存入resolversMapworker 回传{ id, output }时handleMessage找到对应 resolver 并清除。超时仅 reject 该请求对应的 resolver——它不会中断 worker 内部正在执行的 Python这是理解超时语义的关键。IPC 兼容通道PyodideService在模块加载时注册了遗留的IpcChannel.Python_ExecutionRequest渲染进程事件监听PyodideService.ts收到请求后调用自身runScript并通过IpcChannel.Python_ExecutionResponse回传结果。两个通道在 IpcChannel.ts 中定义Python_ExecutionRequest python:execution-request, Python_ExecutionResponse python:execution-response,这意味着主进程main process的调用方也能复用同一个 worker 执行 Python 脚本服务层天然支持渲染进程 UI 与主进程两条入口。Worker 内部行为pypodide.worker.ts 是实际的执行容器。Worker 从 jsDelivr 加载 Pyodide 0.28.0const PYODIDE_INDEX_URL https://cdn.jsdelivr.net/pyodide/v0.28.0/full/ const PYODIDE_MODULE_URL PYODIDE_INDEX_URL pyodide.mjs因此首次使用以及引入新包时都需要网络访问。运行时通过loadPyodide的stdout/stderr回调把标准输出和错误累积到模块级output对象中。对于每个请求worker 依次执行创建全新的 Python globals 字典globals pyodide.globals.get(dict)()保证请求间状态隔离注入 context可选worker 已实现 context 注入逻辑——当消息携带非空context时将其JSON.stringify后经json.loads往返写入 globals注释明确指出这样可避免 Pyodide 0.28 将 JSnull转为jsnull而非None的问题确保注入的全是 Python 原生类型。不过当前 CodeBlockView.tsx 的 UI 调用路径传入的是空对象{}context字段虽然属于服务消息结构的一部分但从 UI 路径来看暂未实际携带数据调用loadPackagesFromImports(python)自动识别源码中的 import 语句并加载所需包包加载失败会抛出Failed to load required packages: ...错误注入 Matplotlib 垫片当源码包含matplotlib时先运行一段垫片代码MATPLOTLIB_SHIM_CODEpyodide.worker.ts设置MPLBACKENDAGG后端、保存原始plt.show、替换为将当前 figure 保存为 PNG 并转成 base64 data URL 的新show()随后plt.clf()/plt.close()释放图形执行源码output.result await pyodide.runPythonAsync(python, { globals })转换 proxy 结果processResult递归处理——对toJs代理对象调用toJs()对数组和普通对象逐元素转换确保所有结果都能安全结构化克隆回主线程转换失败时返回{ __error__: Result processing failed, details: ... }标记捕获输出与可选图像从 globals 读取pyodide_matplotlib_imageMatplotlib 垫片写入的全局变量作为output.image连同 stdout、stderr、执行错误一起封装销毁 per-request globalsfinally块中执行globals?.destroy()然后postMessage({ id, output })回传结果。Worker 源码注释还明确说明请求的串行化由PyodideService的队列负责——因为 stdout/stderr 回调闭包引用模块级output并发处理请求会互相串扰因此服务层保证同一时刻只有一个请求在途。输出与失败语义PyodideService.formatOutputPyodideService.ts按以下优先级组装用户可见文本优先 stdoutoutput.text存在时直接采用trim()后其次是表达式结果无 stdout 但有result时对象结果JSON.stringify(result, null, 2)美化输出普通值String(result)若结果为{ __error__ }标记则显示Result Error: details追加 stderr / 错误output.error存在时以空行分隔附加到文本末尾空输出兜底以上皆无时返回Execution completed with no output.。失败处理遵循不打扰 UI原则初始化失败、超时、内部异常都不会 reject 外层调用而是 resolve 为用户可读文本。例如超时返回Internal error: Python execution timed out初始化失败返回Initialization failed: 原因。worker 内执行错误则写入output.error带Execution error:前缀同样以文本形式呈现。Matplotlib 场景下被垫片替换的show()会把当前 figure 保存为内存中的 PNG data URLCodeBlockView在StatusBar中同时展示文本结果与该图像altMatplotlib plot。安全边界worker 隔离了计算与 UI 线程但它不是针对不可信 Python 的安全沙箱它从 jsDelivr 下载 Pyodide 运行时与 import 引入的包它直接执行用户提供的源码Python 代码本身不受系统级隔离保护。因此该功能默认关闭chat.code.execution.enabled默认false且必须保持为显式用户设置——只有用户主动开启后运行按钮才会出现在 Python 代码块上。这一设计在 preferenceSchemas.ts 与 CodeBlockView.tsx 中均可得到印证。验证与测试UI 契约层有自动化测试覆盖测试文件为 CodeBlockView.test.tsx运行命令pnpm test:renderer src/renderer/components/CodeBlockView/__tests__/CodeBlockView.test.tsx测试关键断言包括启用执行且语言为 python 时点击运行按钮会以(print(42), {}, 60_000)调用runScript并把返回文本渲染到页面L196-L209allowExecution{false}时抑制运行按钮、保留复制等被动工具L211-L222。由于PyodideService与 worker 层目前没有专门的自动化测试任何涉及服务或 worker 的改动仍需手动验证以下场景对应 code-execution.md 的 Verification 章节首次运行时的运行时下载网络可达性包加载loadPackagesFromImports超时报告chat.code.execution.timeout_minutes生效stdout / stderr 输出Matplotlib 图像输出垫片show()生成 PNG。关键源码速查模块路径职责代码块视图CodeBlockView.tsx运行按钮显隐、调用编排、结果渲染状态栏StatusBar.tsx执行结果文本与图像展示容器服务层PyodideService.tsworker 初始化、请求 ID、resolver、超时、IPC 兼容Workerpyodide.worker.tsPyodide 加载、包解析、Matplotlib 垫片、结果序列化偏好定义preferenceSchemas.ts执行开关与超时配置的类型与默认值IPC 通道IpcChannel.ts主进程复用执行链路的通道名UI 测试CodeBlockView.test.tsx运行按钮与调用参数契约测试赞分享人工智能大模型AI 应用交互助手本地部署【免费下载链接】cherry-studio Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端项目地址https://gitcode.com/CherryHQ/cherry-studio点击查看免费下载相关推荐Cherry Studio 代码执行机制基于 Pyodide 与 Web Worker 的 Python 代码块运行原理Cherry Studio 代码执行机制基于 Pyodide 与 Web Worker 的 Python 代码块运行原理 Cherry Studio 的 PyAI 应用大模型桌面应用本地部署RAGCherry Studio代码执行功能浏览器内Python运行引擎Cherry Studio代码执行功能浏览器内Python运行引擎 Cherry Studio的代码执行功能采用了先进的Web Worker架构将PyodiAI 应用大模型桌面应用本地部署RAGCherry Studio 渲染层组件体系深入解析代码块工作台、Pyodide 执行链路与>Cherry Studio 渲染层组件体系深入解析代码块工作台、Pyodide 执行链路与 data ui 语义契约 Cherry Studio 的共享渲染层AI 应用大模型桌面应用本地部署RAG上一篇Pomoday-v2终极键盘任务管理工具完整指南 下一篇Phaser-Catch-The-Cat:一款基于Phaser 3的HTML5游戏创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价