将Python编译为WebAssembly

Rob*_*bie 61 python emscripten webassembly

我已经读过可以将Python 2.7代码转换为Web程序集,但是我找不到关于如何这样做的明确指南.

到目前为止,我已经使用Emscripten及其所有必要组件为Web程序集编译了一个C程序,因此我知道它正在运行(使用指南:http://webassembly.org/getting-started/developers-guide/)

为了在Ubuntu机器上执行此操作,我必须采取哪些步骤?我是否必须将python代码转换为LLVM bitcode然后使用Emscripten进行编译?如果是这样,我将如何实现这一目标?

saa*_*aaj 107

WebAssembly与asm.js

首先,让我们看一下原则上WebAssemblyasm.js的不同之处,以及是否有可能重用现有的知识和工具.以下是非常好的概述:

让我们概括一下,WebAssembly(MVP,因为它的路线图上有更多内容,大致):

  • 是带有静态类型的AST的二进制格式,可以由现有的JavaScript引擎执行(因此可以执行JIT或编译的AOT),
  • 比JavaScript更紧凑(压缩比较)10到20%,解析速度快一个数量级,
  • 它可以表达更多不适合JavaScript语法的低级操作,读取asm.js(例如64位整数,特殊CPU指令,SIMD等)
  • 可以在某种程度上转换为/来自asm.js.

因此,目前WebAssembly是对asm.js的迭代,仅针对C/C++.

Web上的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,有几个现有项目:

  1. PyPy:PyPy.js(作者在PyCon上演讲).这是发布回购.主要的JS文件,pypyjs.vm.js是13 MB(2MB后gzip -6)+ Python stdlib +其他东西.
  2. CPython:pyodide,EmPython,CPython-Emscripten,EmCPythonempython.js是5.8 MB(之后2.1 MB gzip -6),没有stdlib.
  3. Micropython:这个叉子.

    那里没有构建的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 
    
    Run Code Online (Sandbox Code Playgroud)

    它产生micropython.js1.1 MB(之后225 KB gzip -d).如果你只需要非常合规的实现而没有stdlib,那么后者已经需要考虑了.

    要生成WebAssembly构建,您可以更改Makefileto的第13行

    CC = emcc -s RESERVED_FUNCTION_POINTERS=20 -s WASM=1
    
    Run Code Online (Sandbox Code Playgroud)

    然后make -j产生:

    113 KB micropython.js
    240 KB micropython.wasm
    
    Run Code Online (Sandbox Code Playgroud)

    您可以查看HTML输出emcc hello.c -s WASM=1 -o hello.html,以了解如何使用这些文件.

    这样,您还可以在WebAssembly中构建PyPy和CPython,以在兼容的浏览器中解释您的Python应用程序.

另一个可能有趣的事情是Nuitka,一个Python到C++的编译器.可能有可能将您的Python应用程序构建到C++,然后与CPython一起使用Emscripten进行编译.但实际上我不知道该怎么做.

解决方案

从目前来看,如果你正在建设一个传统的网站或网络应用程序,其中下载数兆字节的JS文件仅仅是一个选项,看看的Python到JavaScript transpilers(如Transcrypt)或JavaScript Python实现(例如Brython).或者从编译为JavaScript的语言列表中与其他人一起试试运气.

否则,如果下载大小不是问题,并且您已准备好处理大量粗糙边缘,请在上述三个之间进行选择.

  • 那些 .js 和 .wasm 大小并不公平。流压缩得到了很好的支持,可用于减小两者的大小。相同的文件有多大,gzip 压缩?除此之外,很好的答案。 (2认同)
  • @HaMAD 使用是因为 Rust 对编译到 WASM 具有良好的支持,这意味着您有可能将 Python 的 Rust 端口编译到 WASM。您也可以将 C 程序编译为 WASM,但我不确定让它工作有多好。 (2认同)

Gre*_*egD 6

简而言之:有转译器,但你不能自动将任意 Python 转换为 WebAssembly,我怀疑你能在很长一段时间内做到这一点。尽管理论上这些语言同样强大,并且始终可以进行手动翻译,但 Python 允许某些数据结构和表达模式,这需要非常智能的跨语言编译器(或转译器)[见下文]。解决方法可能是 Python 到 C 到 Web Assembly,因为 Python 到 C 的技术相当成熟,但这通常也行不通,因为 Python 到 C 也很脆弱(见下文)。

正如您在http://webassembly.org/docs/high-level-goals/ 上看到的,WebAssembly 专门针对类 C 语言

从 Python 到 C 的转换可以使用 PyPy 之类的工具来完成,它已经开发了很长时间,但仍然不适用于任意 Python 代码。有几个原因:

  1. Python 有一些非常方便、抽象和漂亮的数据结构,但它们很难转换为静态代码。
  2. Python 依赖于动态垃圾收集。
  3. 大多数 Python 代码严重依赖于各种库,每个库都有自己的怪癖和问题(例如用 C 编写,甚至是汇编程序)。

如果您更仔细地研究为什么 Python-to-C(或 Python 到 C++)如此棘手,您可以看到这个简洁答案背后的详细原因,但我认为这超出了您的问题范围。