将 Python 编译为 WebAssembly

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44761748/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 00:25:52  来源:igfitidea点击:

Compiling Python to WebAssembly

pythonemscriptenwebassembly

提问by Robbie

I have read that it is possible to convert Python 2.7 code to Web Assembly, but I cannot find a definitive guide on how to to so.

我已经读到可以将 Python 2.7 代码转换为 Web Assembly,但我找不到有关如何转换的明确指南。

So far I have compiled a C program to Web Assembly using Emscripten and all its necessary components, so I know it is working (guide used: http://webassembly.org/getting-started/developers-guide/)

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

What are the steps I must take in order to do this on an Ubuntu machine? Do I have to convert the python code to LLVM bitcode then compile it using Emscripten? If so, how would I achieve this?

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

回答by saaj

WebAssembly vs asm.js

WebAssembly 与 asm.js

First, let's take a look how, in principle, WebAssemblyis different from asm.js, and whether there's potential to reuse existing knowledge and tooling. The following gives pretty good overview:

首先,让我们看看原则上WebAssemblyasm.js有何不同,以及是否有重用现有知识和工具的潜力。下面给出了很好的概述:

Let's recapitulate, WebAssembly (MVP, as there's more on its roadmap, roughly):

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

  • is a binary format of AST with static typing, which can be executed by existing JavaScript engines (and thus JIT-able or compiled AOT),
  • it's 10-20% more compact (gzipped comparison) and an order of magnitude faster to parse than JavaScript,
  • it can express more low-level operation that won't fit into JavaScript syntax, read asm.js (e.g. 64-bit integers, special CPU instructions, SIMD, etc)
  • is convertible (to some extent) to/from asm.js.
  • 是具有静态类型的 AST 二进制格式,可以由现有的 JavaScript 引擎执行(因此可以 JIT 或编译的 AOT),
  • 它比 JavaScript 紧凑 10-20%(gzipped 比较)并且解析速度快一个数量级,
  • 它可以表达更多不适合 JavaScript 语法的低级操作,读取 asm.js(例如 64 位整数、特殊 CPU 指令、SIMD 等)
  • 可转换(在某种程度上)到/从 asm.js。

Thus, currently WebAssembly is an iteration on asm.js and targets only C/C++.

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

Python on the Web

网络上的 Python

It doesn't look like GC is the only thing that stops Python code from targeting WebAssembly/asm.js. Both represent low-level statically typed code, in which Python code can't (realistically) be represented. As current toolchain of WebAssembly/asm.js is based on LLVM, a language that can be easily compiled to LLVM IR can be converted to WebAssembly/asm.js. But alas, Python is too dynamic to fit into it as well, as proven by Unladen Swallowand several attemptsof PyPy.

看起来 GC 并不是阻止 Python 代码针对 WebAssembly/asm.js 的唯一因素。两者都表示低级静态类型代码,其中无法(实际上)表示 Python 代码。由于当前的 WebAssembly/asm.js 工具链是基于 LLVM 的,因此可以轻松编译为 LLVM IR 的语言可以转换为 WebAssembly/asm.js。但遗憾的是,正如Unladen Swallow和PyPy 的几次尝试所证明的那样,Python 太动态了,无法适应它。

This asm.js presentation has slides about the state of dynamic languages. What it means is that currently it's only possible to compile whole VM (language implementation in C/C++) to WebAssembly/asm.js and interpret (with JIT where possible) original sources. For Python there're several existing projects:

这个 asm.js 演示有关于动态语言状态的幻灯片。这意味着目前只能将整个 VM(C/C++ 语言实现)编译为 WebAssembly/asm.js 并解释(尽可能使用 JIT)原始源。对于 Python,有几个现有项目:

  1. PyPy: PyPy.js(author's talk at PyCon). Here's release repo. Main JS file, pypyjs.vm.js, is 13 MB (2MB after gzip -6) + Python stdlib + other stuff.
  2. CPython: pyodide, EmPython, CPython-Emscripten, EmCPython, etc. empython.jsis 5.8 MB (2.1 MB after gzip -6), no stdlib.
  3. Micropython: this fork.

    There was no built JS file there, so I was able to build it with trzeci/emscripten/, a ready-made Emscripten toolchain. Something like:

    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 
    

    It produces micropython.jsof 1.1 MB (225 KB after gzip -d). The latter is already something to consider, if you need only very compliant implementation without stdlib.

    To produce WebAssembly build you can change line 13 of the Makefileto

    CC = emcc -s RESERVED_FUNCTION_POINTERS=20 -s WASM=1
    

    Then make -jproduces:

    113 KB micropython.js
    240 KB micropython.wasm
    

    You can look at HTML output of emcc hello.c -s WASM=1 -o hello.html, to see how to use these files.

    This way you can also potentially build PyPy and CPython in WebAssembly to interpret your Python application in a compliant browser.

  1. PyPy:PyPy.js(作者在 PyCon 上演讲)。这是发布回购。主 JS 文件pypyjs.vm.js13 MB(之后 2MB gzip -6)+ Python stdlib + 其他东西。
  2. CPython:pyodideEmPythonCPython-EmscriptenEmCPythonempython.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 
    

    它产生micropython.js1.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 应用程序。

Another potentially interesting thing here is Nuitka, a Python to C++ compiler. Potentially it can be possible to build your Python app to C++ and then compile it along with CPython with Emscripten. But practically I've no idea how to do it.

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

Solutions

解决方案

For the time being, if you're building a conventional web site or web app where download several-megabyte JS file is barely an option, take a look at Python-to-JavaScript transpilers (e.g. Transcrypt) or JavaScript Python implementations (e.g. Brython). Or try your luck with others from list of languages that compile to JavaScript.

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

Otherwise, if download size is not an issue, and you're ready to tackle a lot of rough edges, choose between the three above.

否则,如果下载大小不是问题,并且您已准备好解决很多问题,请在上述三个中进行选择。

回答by Malcolm White

This won't be possible until web assembly implements garbage collection. You can follow progress here: https://github.com/WebAssembly/proposals/issues/16

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

回答by GregD

In short: you can't convert arbitrary Python to Web Assembly, and I doubt you will be able to for a long time to come. A workaround might be Python to C to Web Assembly, but that isn't generally going to work either since Python-to-C is fragile (see below).

简而言之:您无法将任意 Python 转换为 Web Assembly,而且我怀疑在未来很长一段时间内您是否能够做到。一种解决方法可能是 Python 到 C 到 Web 程序集,但这通常也不会奏效,因为 Python 到 C 是脆弱的(见下文)。

WebAssembly is specifically targeted to C-like languages as you can see at http://webassembly.org/docs/high-level-goals/

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

Translating from Python to C can be done with tools like PyPy, which has been under development for a long time, but which still does not work for arbitrary Python code. There are several reasons for this:

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

  1. Python has some very handy, abstract and nice data structures, but they are hard to translate into static code.
  2. Python depends on dynamic garbage collection.
  3. Most Python code depends heavily on various libraries, each of which has it's own quirks and issues (such as being written in C, or even assembler).
  1. Python 有一些非常方便、抽象和漂亮的数据结构,但它们很难转换为静态代码。
  2. Python 依赖于动态垃圾收集。
  3. 大多数 Python 代码严重依赖于各种库,每个库都有自己的怪癖和问题(例如用 C 编写,甚至是汇编程序)。

If you look more carefully into why Python-to-C (or Python to C++) has been so tricky you can see the detailed reasons behind this terse answer, but I think that's outside the scope of your question.

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