WebAssembly 与 asm.js
首先,让我们看看WebAssembly在原则上与asm.js有何不同,以及是否有可能重用现有知识和工具。下面给出了很好的概述:
让我们概括一下,WebAssembly(MVP,因为它的路线图上还有更多内容,粗略):
- 是一种具有静态类型的 AST 二进制格式,可以由现有的 JavaScript 引擎执行(因此可以执行 JIT 或编译的 AOT),
- 它比 JavaScript 紧凑 10-20%(gzipped 比较)并且解析速度快一个数量级,
- 它可以表达更多不适合 JavaScript 语法的低级操作,读取 asm.js(例如 64 位整数、特殊 CPU 指令、SIMD 等)
- 可(在某种程度上)与 asm.js 相互转换。
因此,目前 WebAssembly 是 asm.js 的迭代,仅针对 C/C++(和类似语言)。
网络上的 Python
看起来 GC 并不是唯一阻止 Python 代码以 WebAssembly/asm.js 为目标的东西。两者都代表低级静态类型代码,其中 Python 代码不能(实际上)表示。由于当前 WebAssembly/asm.js 的工具链是基于 LLVM 的,因此可以轻松编译为 LLVM IR 的语言可以转换为 WebAssembly/asm.js。但可惜的是,Python 的动态性太大,无法融入其中,Unladen Swallow和PyPy 的几次尝试都证明了这一点。
这个 asm.js 演示文稿有关于动态语言状态的幻灯片。这意味着目前只能将整个 VM(C/C++ 中的语言实现)编译为 WebAssembly/asm.js 并解释(尽可能使用 JIT)原始源。对于 Python,有几个现有项目:
PyPy:PyPy.js(作者在 PyCon 的演讲)。这是发布回购。主 JS 文件pypyjs.vm.js
13 MB(之后 2MB gzip -6
)+ Python stdlib + 其他东西。
CPython:pyodide、EmPython、CPython-Emscripten、EmCPython等empython.js
为 5.8 MB(之后为 2.1 MB gzip -6
),没有 stdlib。
Micropython:这个 fork。
那里没有构建的 JS 文件,所以我可以使用trzeci/emscripten/
现成的 Emscripten 工具链来构建它。就像是:
git clone https://github.com/matthewelse/micropython.git
cd micropython
docker run --rm -it -v $(pwd):/src trzeci/emscripten bash
apt-get update && apt-get install -y python3
cd emscripten
make -j
# to run REPL: npm install && nodejs server.js
它产生micropython.js
1.1 MB(之后为 225 KB gzip -d
)。如果您只需要非常合规的实现而不需要 stdlib,则后者已经是需要考虑的事情了。
要生成 WebAssembly 构建,您可以将第 13 行更改Makefile
为
CC = emcc -s RESERVED_FUNCTION_POINTERS=20 -s WASM=1
然后make -j
产生:
113 KB micropython.js
240 KB micropython.wasm
您可以查看 的 HTML 输出emcc hello.c -s WASM=1 -o hello.html
,了解如何使用这些文件。
通过这种方式,您还可以潜在地在 WebAssembly 中构建 PyPy 和 CPython,以在兼容的浏览器中解释您的 Python 应用程序。
这里另一个可能有趣的东西是Nuitka,一个 Python 到 C++ 的编译器。有可能将您的 Python 应用程序构建为 C++,然后使用 Emscripten 将其与 CPython 一起编译。但实际上我不知道该怎么做。
解决方案
目前,如果您正在构建一个传统的网站或 Web 应用程序,下载几兆字节的 JS 文件几乎是不可能的,请查看 Python 到 JavaScript 的转译器(例如 Transcrypt )或 JavaScript Python 实现(例如Brython)。或者从编译为 JavaScript 的语言列表中与其他人一起试试运气。
否则,如果下载大小不是问题,并且您已经准备好解决很多问题,请在上述三个之间进行选择。
2020 年第三季度更新
JavaScript 端口被集成到 MicroPython 中。它位于
ports/javascript中。
该端口以名为MicroPython.js的 npm 包的形式提供。您可以在RunKit中尝试一下。
Rust 中有一个积极开发的 Python 实现,称为
RustPython。因为 Rust 官方支持WebAssembly 作为编译目标,所以在自述文件的顶部有演示链接也就不足为奇了。虽然,现在还早。他们的免责声明如下。
RustPython 处于开发阶段,不应在生产或容错设置中使用。
我们当前的构建只支持 Python 语法的一个子集。