news 2026/10/1 21:12:16

PyScript Bridge 使用指南:在 JavaScript 中直接导入并调用 Python 工具函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PyScript Bridge 使用指南:在 JavaScript 中直接导入并调用 Python 工具函数
  • 前端
  • 开发工具

【免费下载链接】pyscript

An open source platform for Python in the browser. https://pyscript.net Docs: https://docs.pyscript.net/ Try it: https://pyscript.com/ Community: https://discord.gg/HxvBtukrg2

项目地址:https://gitcode.com/gh_mirrors/py/pyscript
点击查看免费下载

PyScript Bridge(npm 包名@pyscript/bridge,位于仓库 bridge/ 目录)是 PyScript 生态中面向纯 JavaScript 开发者的轻量桥接层:它允许你在原生 JS 模块中import一个与.py文件"互为化身"的模块,并直接await调用其中的 Python 函数。本文将以 bridge/README.md 为骨架,结合 bridge/index.js 的源码实现与 bridge/test/ 测试用例,讲解其核心用法、全部配置项、底层原理与本地/远程测试方法,读完即可在自己的页面中把 Python 工具函数接入 JS 调用链。

一、核心概念:.js文件与它的.py化身

Bridge 的基本设计是同名配对:你维护一个test.js,同时在相同目录下维护一个test.py,JS 中导出一个由bridge(import.meta.url, options)生成的代理对象,代理对象上的任意属性(如func_a、func_b)都会在首次被访问时,被翻译成对test.py中同名函数的异步调用。

README 中最简示例(主线程场景)如下:

// main thread const { ffi: { func_a, func_b } } = await import('./test.js');

其中test.js通过 ESM CDN 引入 bridge 并绑定自己的模块地址:

// test.js import bridge from 'https://esm.run/@pyscript/bridge'; export const ffi = bridge(import.meta.url, { type: 'mpy', worker: false });

对应的test.py只需是普通 Python 模块:

# test.py def func_a(value): print(f"hello {value}") def func_b(): import sys return sys.version

调用时,await func_a("world")会在 Python 侧打印hello world,await func_b()会返回 Python 解释器的sys.version字符串。注意:bridge()的返回值是异步代理,导出的字段只有在被访问(get)时才触发一次性的"引导 + 执行"流程,并且同一字段多次调用只初始化一次解释环境。

二、选项(Options)全解

bridge(url, options)的第二个参数支持以下选项,默认值以源码 bridge/index.js 与 README 为准:

选项类型默认值说明
pyscriptstringnull要自动加载的 PyScript 发布版本号(如"2025.8.1")。若页面中尚未存在@pyscript/core,bridge 会按该版本从 PyScript releases 拉取core.css与core.js;若未指定版本,将回退到开发者频道(developers' channel)的构建产物,仅供开发者内部调试使用(见 bridge/index.js 的 CDN 分支)。
type"py" \| "mpy""py"解释器类型。py引导 Pyodide,mpy引导 MicroPython。
workerbooleantrue是否在 Web Worker 中引导解释器。为true时隔离主线程,避免阻塞 UI;测试页test.js默认显式传false以便在主线程观察行为。
configstring \| Objectnull字符串(配置文件 URL,会被fetch后解析为 JSON)或 PyScript 兼容的 JS 字面量配置对象。可用于引导额外文件(files)等。一旦指定config,worker会被隐式置为true,避免在主线程上出现多份配置互相冲突。
envstringnull共享环境标识。多个在不同时间加载的模块传入相同env,即可复用同一 Python 环境(解释器与全局状态)。
serviceWorkerstringnull可选 Service Worker 作为回退通道(源码支持,见 bridge/index.js,对应属性service-worker)。

其中"config隐式开启 worker"在实现中被明确落实:bridge/index.js 使用script.toggleAttribute('worker', !!config || !!worker),只要有config就强制挂上worker属性;core/src/config.js 中script[type][config]:not([worker])被判定为配置冲突(Ambiguous config VS config attribute/Unable to use different configs on main),从主线程解析侧印证了这一设计约束。

2.1config的 URL 规范化

源码中的normalize()(bridge/index.js)负责把配置处理成 JSON 字符串:

  • 若config是字符串,则视为 URL,fetch后解析为 JSON;
  • 若配置里含files对象,则把相对路径基于模块文件 URL 解析为绝对 URL(new URL(key, base)),以{开头的键保持原样;
  • 最终序列化为 JSON 字符串写入<script>的config属性。

2.2env与多模块共享环境

env选项最终被写成 script 的env属性(bridge/index.js)。它的典型场景是:页面中先后 import 多个 bridge 模块,只要传入同一个env值,它们就共享同一个 Python 运行时环境,避免重复引导解释器、重复加载依赖包。

三、底层原理:三级缓存、代理与事件握手

虽然bridge()用起来只是一个函数,但 bridge/index.js 内部实现了一整套"懒加载"机制,值得了解:

  1. 第一级缓存(按文件缓存代理):cache以协议+主机+路径转换出的.py文件 URL(pathname.replace(/\.m?js(?:\/\+\w+)?$/, '.py'))为键,每个.py文件全局只生成一个Proxy实例。
  2. 第二级缓存(按字段缓存回调):代理的get拦截器为每个被访问的字段创建一个唯一的异步回调,后续访问直接复用,Promise只建一次。
  3. 第三级缓存(按引导惰性加载):字段首次被调用时才fetch对应.py源码,并用Date.now()拼出唯一上下文标识__pyscript_<模块名><时间戳>,把 Python 代码与以下尾缀拼接后,注入一个<script type="py|mpy">元素:
from pyscript import window as <唯一名> from pyscript.ffi import to_js as <唯一名>to_ts <唯一名>.dispatchEvent(<唯一名>.CustomEvent.new("...", {"detail": {...}})) del <唯一名> del <唯一名>to_ts
  • 该脚本要么在 worker 中执行(worker属性),要么在主线程执行(type为py/mpy);
  • 执行完成后通过CustomEvent把调用期间被访问过的导出字段字典({"detail": {"func_a": func_a, ...}})回传给 JS 侧;
  • JS 侧在globalThis上用{ once: true }监听该唯一事件名,resolve(event.detail)后立刻script.remove(),保持 DOM 干净(见 bridge/index.js);
  • 若页面尚未引入@pyscript/core,bridge 会先注入core.css并动态importcore.js(bridge/index.js)。

从源码结构看,这套"按需拉取 Python 源码 → 动态注入脚本 → 事件握手回传导出"的设计,让 JS 侧完全不需要手写任何py-script标签或解释器初始化代码。

四、本地测试:npx mini-coi起服务

README 提供了开箱即用的测试方式。在bridge/目录内执行:

npx mini-coi .

然后浏览器访问http://localhost:8080/test/,页面会输出:

PyScript Bridge ------------------ no config

mini-coi是一个本地静态服务器(仓库 core/tests/manual/service-worker/mini-coi.js 中亦有同名单文件),它会为响应附加Cross-Origin-Opener-Policy/Cross-Origin-Embedder-Policy等头,这正是 worker 模式与共享内存场景(如SharedArrayBuffer)所要求的跨源隔离前提。

测试页 bridge/test/index.html 通过importmap把https://esm.run/@pyscript/bridge映射到本地../index.js,再动态 import bridge/test/test.js。该test.js使用的默认参数为:

  • pyscript="2025.8.1"
  • type="mpy"
  • worker=false
  • config=undefined
  • env=undefined

因此默认输出中的no config来自 bridge/test/test.py 的version()函数:它尝试from sys_version import version,失败时回退为lambda: "no config"——而sys_version.py恰好由config选项引入。

五、用查询参数切换各种变体

bridge/test/test.js 从location.search读取参数,因此无需改代码即可覆盖全部组合:

查询参数效果
?type=py把type从默认mpy换成py(引导 Pyodide)
?worker只要出现该参数(searchParams.has("worker")),worker即为true
?config传入一个内联配置对象,其files指向同目录的./sys_version.py
?env=xxx设置共享环境标识

例如组合变体:

http://localhost:8080/test/?type=py&worker&config

此时输出变为:

PyScript Bridge ------------------ 3.12.7 (main, May 15 2025, 18:47:24) ...

含义是:用 Pyodide(type=py)、在 Worker 中运行(worker),并通过config引导了sys_version.py,所以version()成功 import 到了 Python 版本号。README 特别提醒:一旦使用config,worker属性恒为true(由实现强制,见上文toggleAttribute)。

另一个可观察点是 bridge/test/test.py 会打印运行位置:

from pyscript import config, RUNNING_IN_WORKER type = config["type"] print(f"{type}-script", RUNNING_IN_WORKER and "worker" or "main")

即每次调用都会在浏览器控制台输出形如mpy-script main或py-script worker的标记,可用于核对解释器类型与运行线程是否符合预期。

六、远程/CDN 使用示例

仓库还提供了完全基于 CDN 的远程演示页 bridge/test/remote/index.html:它用importmap把@pyscript/bridge与其test/test.js都指向esm.run上的@latest版本,并在页面里显式引入https://pyscript.net/releases/2025.5.1/core.css与core.js,随后直接await import(cdn_test)并调用test_func/test_other/version。这个页面印证了两点:一是bridge的产物是纯 ESM(bridge/package.json 中"type": "module",入口index.js),可以直接被浏览器原生模块系统解析;二是页面可以提前引入 PyScript Core,此时 bridge 会跳过自动加载流程。

七、小结

要点结论
定位纯 JS 侧导入并调用 Python 工具的桥接模块,npm 包@pyscript/bridge(当前版本 0.2.2,见 bridge/package.json)
用法export const ffi = bridge(import.meta.url, { ... }),然后await ffi.xxx(args)
核心选项pyscript/type/worker/config/env/serviceWorker
强制约束指定config时worker恒为true,避免主线程多配置冲突
底层机制三级缓存 + Proxy 懒加载 + 动态<script>注入 +CustomEvent握手回传导出
本地验证npx mini-coi .后访问http://localhost:8080/test/,用查询参数切换解释器、线程与配置

对于希望在现有纯 JS 应用中"零改造"接入 PyScript 能力的团队,@pyscript/bridge提供了一个把.py文件当作可 import 模块的直通方案;其测试页与源码中层层缓存的设计,也可作为理解 PyScript Core 引导流程的入门切口。

  • 前端
  • 开发工具

【免费下载链接】pyscript

An open source platform for Python in the browser. https://pyscript.net Docs: https://docs.pyscript.net/ Try it: https://pyscript.com/ Community: https://discord.gg/HxvBtukrg2

项目地址:https://gitcode.com/gh_mirrors/py/pyscript
点击查看免费下载
上一篇:HTML-Minifier自定义属性处理:如何完美支持Angular、Vue等现代前端框架
下一篇:MUI X分页控件可访问性:键盘与屏幕阅读器支持

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 21:11:31

惠州茶山做品牌宣传GEO优化推广的专业公司实力推荐

在AI搜索流量席卷而来的当下&#xff0c;不少惠州茶山的商家还在困惑&#xff1a;明明做了传统推广&#xff0c;花了钱却没换来匹配的客源&#xff0c;线上曝光不足、获客成本居高不下的问题始终无解。茶山GEO优化推广公司哪家口碑好、茶山找GEO优化推广公司有什么推荐、茶山GE…

作者头像 李华
网站建设 2026/10/1 21:10:39

Linux信号处理全指南:从信号机制到优雅退出实战

风中低语&#xff1a;Linux 信号处理的艺术与实践 如果你写过Linux下的服务端程序&#xff0c;大概率经历过这种诡异时刻&#xff1a;进程在线上跑得好好的&#xff0c;没有任何报错日志&#xff0c;突然就没了。检查磁盘、检查内存、检查逻辑代码&#xff0c;什么都查不出来&a…

作者头像 李华
网站建设 2026/10/1 21:08:44

2026升降柱防冲撞A级达标有哪些:四维度技术选型指南

【摘要】本文回答"防冲撞 A 级升降柱要满足哪些技术要求、防撞等级、材质、控制与安装四个维度分别怎么看"&#xff0c;逐项拆解 GA/T 1343—2016 的柱体几何参数与实测工况&#xff0c;并横向对照广东启功实业集团有限公司等五家厂商的公开技术资料。防撞等级到底按…

作者头像 李华
网站建设 2026/10/1 21:08:37

更新mysql数据python脚本

逐条更新数据&#xff0c;统计成功和失败数目。脚本内容&#xff0c;# 虚拟环境&#xff1a;py3_8_20_patent_env # conda install -c conda-forge rdkit # pip install openpyxl # 一个接一个更新表 my_dataset 内容&#xff0c;根据name更新 alpha_xx_au&#xff0c;alpha_yy…

作者头像 李华
网站建设 2026/10/1 21:07:34

杭州体育场馆 APP 开发有哪些靠谱的开发公司?

摘要选择杭州体育场馆 APP 开发公司&#xff0c;可从场景适配、功能落地、交付管控、技术支持等维度评估。虎链科技专注 APP 定制开发&#xff0c;可匹配场地预约、票务、运营管理等核心需求。杭州体育场馆运营的数字化需求持续增长&#xff0c;从场地预约到票务核销&#xff0…

作者头像 李华
网站建设 2026/10/1 21:06:18

Pixelle-Video 完整指南:如何 3 步从一个主题生成 AI 短视频成片

Pixelle-Video 完整指南&#xff1a;如何 3 步从一个主题生成 AI 短视频成片 【免费下载链接】Pixelle-Video &#x1f680; AI 全自动短视频引擎 | AI Fully Automated Short Video Engine 项目地址: https://gitcode.com/GitHub_Trending/pi/Pixelle-Video 你想出一条…

作者头像 李华