将Python编译为WebAssembly

问题描述 投票:54回答:3

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

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

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

python emscripten webassembly
3个回答
95
投票

WebAssembly vs asm.js

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

让我们重新概括一下,WebAssembly(MVP,就像its roadmap上的更多内容,粗略地说):

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

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

Python on the Web

它看起来不像GC是阻止Python代码定位WebAssembly / asm.js的唯一因素。两者都代表低级静态类型代码,其中Python代码不能(现实地)表示。由于WebAssembly / asm.js的当前工具链基于LLVM,因此可以轻松编译为LLVM IR的语言可以转换为WebAssembly / asm.js。但是唉,Python太活泼了,不适合它,正如pypy的Unladen Swallowseveral attempts所证明的那样。

这个asm.js演示文稿有slides about the state of dynamic languages。这意味着目前只能将整个VM(C / C ++中的语言实现)编译为WebAssembly / asm.js并解释(在可能的情况下使用JIT)原始源。对于Python,有几个现有项目:

  1. PyPy:PyPy.js(作者的talk at PyCon)。这是release repo。主要的JS文件,pypyjs.vm.js,是13 MB(gzip -6之后2MB)+ Python stdlib +其他东西。
  2. CPython:pyodideEmPythonCPython-EmscriptenEmCPython等.empython.js是5.8 MB(gzip -6后2.1 MB),没有stdlib。
  3. Micropython:this 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 它产生1.1 MB的micropython.js(在gzip -d之后为225 KB)。如果你只需要非常合规的实现而没有stdlib,那么后者已经需要考虑了。 要生成WebAssembly构建,您可以将Makefile的第13行更改为 CC = emcc -s RESERVED_FUNCTION_POINTERS=20 -s WASM=1 然后make -j产生: 113 KB micropython.js 240 KB micropython.wasm 您可以查看emcc hello.c -s WASM=1 -o hello.html的HTML输出,以了解如何使用这些文件。 这样,您还可以在WebAssembly中构建PyPy和CPython,以在兼容的浏览器中解释您的Python应用程序。

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

Solutions

目前,如果您正在构建一个传统的网站或Web应用程序,其中下载几兆字节的JS文件几乎不可用,请查看Python-to-JavaScript转换器(例如Transcrypt)或JavaScript Python实现(例如Brython) )。或者试试与list of languages that compile to JavaScript的其他人的运气。

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


4
投票

在Web程序集实现垃圾收集之前,这是不可能的。你可以在这里关注进展:https://github.com/WebAssembly/proposals/issues/16


3
投票

简而言之:你无法将任意Python转换为Web Assembly,我怀疑你能在很长一段时间内完成。解决方法可能是Python到C到Web程序集,但由于Python-to-C很脆弱,因此通常不会起作用(见下文)。

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

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

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

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