将Python编译为WebAssembly

时间:2017-06-26 14:13:31

标签: python emscripten webassembly

我已经读过可以将Python 2.7代码转换为Web程序集,但我找不到关于如何执行此操作的明确指南。

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

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

3 个答案:

答案 0 :(得分:93)

WebAssembly与asm.js

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

让我们重新概括一下,WebAssembly(MVP,大致上its roadmap还有更多内容):

  • 是带有静态类型的AST的二进制格式,可以由现有的JavaScript引擎执行(因此可以执行JIT或编译AOT),
  • 比JavaScript更紧凑(gzipped比较)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太活泼了,不适合它,正如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.jsgzip -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应用程序。

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

    解决方案

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

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

答案 1 :(得分:4)

在Web程序集实现垃圾收集之前,这是不可能的。您可以在此处关注进度:https://github.com/WebAssembly/design/issues/1079

答案 2 :(得分:3)

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

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

看到

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

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

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