
Pyodide 314.0 发布:Python 包可直接发布 WebAssembly wheels 到 PyPI
Pyodide 314.0 迎来里程碑式更新:PEP 783 被正式采纳,Python 包维护者现在可以将 Emscripten 平台的 WebAssembly wheels 直接发布到 PyPI,无需经过 Pyodide 核心团队的手动构建。
原文来源:Pyodide 官方博客 — Pyodide 314.0 正式发布,PEP 783 让 Python 包可直接发布 WebAssembly wheels 到 PyPI,版本号与 Python 3.14 对齐,恢复了 ssl/sqlite3/lzma 标准库,新增原生 ES Module 支持和实验性 Node.js Socket 支持。
发生了什么?
Pyodide 314.0 刚刚发布了。这可不是一次普通的版本号递增——这是 Pyodide 历史上最重要的一次平台升级。
如果你还不熟悉 Pyodide,简单说它就是一个把 CPython 编译到 WebAssembly 的项目,让你能在浏览器里直接运行 Python,不需要任何服务器端。NumPy、Pandas、Matplotlib、SciPy 这些重量级科学计算库,全都能在浏览器里跑。
而 314.0 版本的核心变化是:PEP 783 被 Python 指导委员会正式采纳了。
—— 广告 ——
PEP 783 到底意味着什么?
这是本次更新最值得关注的事情。
以前是什么样?
在过去,如果你的 Python 包包含 C 扩展(比如说你用 Cython 写了一些加速代码),想要在 Pyodide 里运行,你得走这条路:
- 你的包必须被 Pyodide 核心团队收录到他们的「300+ 内置包列表」里
- Pyodide 团队手动用 Emscripten 交叉编译你的包
- 用户通过
pyodide.loadPackage('你的包名')才能加载
这意味着你的包的发布节奏完全受制于 Pyodide 的发布周期。你修了个 bug,发布了新版本,但用户要等到下一个 Pyodide 版本才能用上。
现在呢?
PEP 783 定义了一个新的 Python 平台标签:pyemscripten_2026_0(对应 Python 3.14 / Pyodide 314.x)和 pyemscripten_2025_0(对应 Python 3.13 / Pyodide 0.29.x)。
这意味着:
你作为包维护者,可以直接用 pyodide-build 或 cibuildwheel 编译出带
pyemscripten标签的 wheel,把它上传到 PyPI。用户在 Pyodide 里用micropip.install('你的包')就能安装了。
简单说:从 Pyodide 内置 → 发布到 PyPI,从「等官方收录」变成「自己发布」。
cibuildwheel 已经支持了
如果你已经在用 cibuildwheel 做 CI 自动化构建,好消息是 cibuildwheel v4.0 已经支持 PyEmscripten 2025 和 2026 ABI(2026 版目前是 prerelease,v4.1.0 会稳定化)。
这意味着你在 CI 配置里加上 Emscripten 平台,就能在每次发布时自动构建跨平台的 wheel,包括 WebAssembly 版本。整个流程和发布一个 Linux x86_64 wheel 没有本质区别。
动手:如何构建你的第一个 WebAssembly wheel
纯 Python 包(无需额外操作)
如果你的包是纯 Python(没有 C 扩展),你什么都不用做。标准 wheel(用 python -m build、hatch、flit 等工具构建)已经在 Pyodide 中兼容。用户直接:
import micropip
await micropip.install("your-package")带 C 扩展的包
如果你的包包含 C 扩展,需要用到 pyodide-build——它是 PEP 783 的参考构建工具链。
安装:
pip install pyodide-build构建:
pyodide build .这会生成一个像这样的 wheel 文件:
your_package-1.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl
这个 wheel 可以直接上传到 PyPI:
twine upload dist/*pyemscripten*pyodide-build 的工作原理是包装了标准的 pypa/build,加上一个交叉编译层。当你运行 pyodide build 时,它:
- 设置 Emscripten 编译环境(包含 CPython 头文件)
- 拦截编译器调用(
gcc→emcc、g++→em++、ld→ 对应 Emscripten 链接器) - 将编译器标志转换为 WebAssembly 兼容格式
- 输出带正确平台标签的标准 wheel
你的 setup.py、pyproject.toml、CMakeLists.txt 或 meson.build 都不需要改动——pyodide-build 透明地处理交叉编译。
更详细指引见 pyodide-build 官方文档。
版本号变了:314.x = Python 3.14
Pyodide 314.0 带来了一个新的版本号方案:
Pyodide 的版本号直接对应 Python 的版本号。314.0 = Python 3.14 的第一个兼容版本。
以前 Pyodide 用 0.x 版本号(比如 0.29.x),用户很难一眼看出它对应哪个 Python 版本。现在一目了然:如果 Pyodide 发布 314.5,那它肯定对应 Python 3.14.5。
这个版本对应 Python 3.14.2 和 Emscripten 5.0.3。以后每年一个主版本,跟着 CPython 的发布节奏走。
标准库变化:三大回归
这个版本恢复了三个之前被剥离的标准库模块:
ssl— 虽然不再基于 OpenSSL(OpenSSL 已从 Pyodide 中移除),但实现了一个自定义版本,保留了大部分非加密功能。真正的 SSL/TLS 功能在浏览器环境中本来就不起作用,所以实际影响有限sqlite3— SQLite 数据库支持完全恢复正常lzma— LZMA 压缩库回来了
这三个库的回归意味着更大的初始下载体积,但用户不再需要单独安装它们。对于用 SQLite 做本地存储、用 lzma 解压数据的应用来说,这是实实在在的便利。
顺便提一句,由于移除了 OpenSSL,hashlib 也失去了部分依赖 OpenSSL 的加密哈希函数。如果你在浏览器中需要完整密码学功能,建议通过 Web Crypto API 来补充。
同时,Python 3.14 新自带的 compression.zstd 模块在 Pyodide 中也可用,开箱即用。
ES Module 迁移:告别 .js 后缀
pyodide.asm.js 被重命名为 pyodide.asm.mjs。如果你在项目中直接引用这个文件,需要更新引用路径:
// 旧方式(不再支持)
// import createPyodideModule from "./pyodide.asm.js";
// 新方式
import createPyodideModule from "./pyodide.asm.mjs";
import { loadPyodide } from "./pyodide.mjs";
loadPyodide({ createPyodideModule }).then((pyodide) => {
// 你的 Python 代码
});需要注意:classic(非 module)worker 模式不再支持。所有 worker 代码必须使用 type: "module"。
Node.js 也能用了:实验性 Socket 支持
这是一个很多人期待的功能——Pyodide 现在可以在 Node.js 中创建 TCP 套接字了。
const pyodide = await loadPyodide();
await pyodide.useNodeSockFS();启用后,你就可以在 Node.js 的 Pyodide 环境中连接数据库了。官方已测试兼容:
pymysql— 连接 MySQLpg8000— 连接 PostgreSQLredis-py— 连接 Redis
支持 TCP 带 TLS、异步套接字函数和非阻塞模式。如果你用的是 Node.js v24 或更早版本,需要加 --experimental-wasm-stack-switching 参数来启用 JSPI。
JavaScript 互操作的大升级
JsBigInt:不再丢失精度
pyodide.ffi.JsBigInt 是一个新的 int 子类,专门用来保留 JavaScript 的 bigint 类型。当你把 JavaScript 的 BigInt 传给 Python 时,不会因为精度丢失变成普通的 Python int。对于需要处理 2^53 以上大数的应用来说,这个功能很关键。
资源管理:using / with
JavaScript 端:PyProxy 和 PyBufferView 现在实现了 [Symbol.dispose],你可以用 JavaScript 的 using 关键字来自动清理:
{
using proxy = pyodide.runPython("some_object()");
// proxy 在代码块结束时自动销毁
}Python 端:任何实现了 [Symbol.dispose]() 的 JavaScript 对象都可以在 Python 中当上下文管理器用:
with js_object as x:
... # 退出时自动调用 x[Symbol.dispose]()异步版本([Symbol.asyncDispose])也支持,适用于需要 await 清理的场景。
更好的类数组支持
以前,JavaScript 的类数组对象(有 length 属性且可迭代)在 Python 中只能通过循环访问元素。现在它们支持下标操作了:
proxy[1:4] # 返回索引 1 到 3 的切片
proxy[::2] # 每隔一个元素这对于处理 JavaScript 的 TypedArray、NodeList 等类数组对象非常方便。
这对开发者意味着什么?
如果你在用 Pyodide 做浏览器端 Python 开发:
- sqlite3 回归让你可以直接在浏览器里用 SQLite 做本地存储,不用再自己找替代方案
- cibuildwheel 支持意味着你可以把 WebAssembly 纳入你的 CI/CD 工作流,每次发布自动构建
- ES Module 支持让 Pyodide 更好地融入现代前端工具链
- Node.js Socket 支持让你能把 Pyodide 用在后端场景,比如 Edge Function 或 Serverless 环境
如果你只是想在浏览器里跑 Python 代码:
- 访问 pyodide.org 的官方 REPL
- 在你的 HTML 页面中引入 Pyodide:
<script src="https://cdn.jsdelivr.net/pyodide/v0.29.0/full/pyodide.js"></script> - 用
await micropip.install("包名")加载你需要的数据科学包
Pyodide 314.0 最令人兴奋的地方,不是它新增了多少功能,而是它让 Python 生态和 WebAssembly 生态的融合变得更加顺畅。当包维护者可以像发布普通 wheel 一样发布 WebAssembly wheel 时,浏览器里的 Python 就不再是一个需要额外维护的「二等公民」,而是 Python 生态真正的扩展。
© 2026 四月 · CC BY-NC-SA 4.0
原文链接:https://aprilzz.com/tutorials/pyodide-314-wasm-wheels