Компиляция Python в WebAssembly

Я прочитал, что можно конвертировать код Python 2.7 в веб-сборку, но я не могу найти окончательное руководство по тому, как это сделать.

До сих пор я скомпилировал C-программу для веб-сборки с использованием Emscripten и всех ее необходимых компонентов, поэтому я знаю, что она работает (руководство используется: http://webassembly.org/getting-started/developers-guide/)

Какие шаги я должен предпринять, чтобы сделать это на машине Ubuntu? Должен ли я преобразовать код python в бит-код LLVM, а затем скомпилировать его с помощью Emscripten? Если да, то как мне это достичь?

Ответы

Ответ 1

WebAssembly против asm.js

Во-первых, давайте посмотрим, чем, в принципе, WebAssembly отличается от asm.js, и есть ли потенциал для повторного использования существующих знаний и инструментов. Следующее дает довольно хороший обзор:

Давайте повторим, WebAssembly (MVP, как там больше на его дорожной карте, примерно):

  • представляет собой двоичный формат AST со статической типизацией, который может выполняться существующими механизмами JavaScript (и, следовательно, JIT-совместимым или скомпилированным AOT),
  • он на 10-20% компактнее (сравнение в сжатом формате) и на порядок быстрее разбирается, чем JavaScript,
  • он может выражать более низкоуровневые операции, которые не вписываются в синтаксис JavaScript, читать asm.js (например, 64-разрядные целые числа, специальные инструкции процессора, SIMD и т.д.)
  • конвертируемо (до некоторой степени) в/из asm.js.

Таким образом, в настоящее время WebAssembly является итерацией для asm.js и предназначена только для C/C++.

Python в Интернете

Не похоже, что GC - единственное, что мешает коду Python ориентироваться на WebAssembly/asm.js. Оба представляют низкоуровневый статически типизированный код, в котором код Python не может (реально) быть представлен. Поскольку текущий набор инструментов WebAssembly/asm.js основан на LLVM, язык, который можно легко скомпилировать в IR LLVM, можно преобразовать в WebAssembly/asm.js. Но, увы, Python слишком динамичен, чтобы в него вписываться, что доказано Unladen Swallow и несколькими попытками PyPy.

Эта презентация asm.js содержит слайды о состоянии динамических языков. Это означает, что в настоящее время возможно только скомпилировать целую ВМ (языковую реализацию в C/C++) в WebAssembly/asm.js и интерпретировать (с JIT, где это возможно) исходные источники. Для Python существует несколько существующих проектов:

  1. PyPy: PyPy.js (авторская беседа на PyCon). Здесь релиз репо. Основной файл JS, pypyjs.vm.js, составляет 13 МБ (2 МБ после gzip -6) + Python stdlib + другие материалы.
  2. CPython: pyodide, EmPython, CPython-Emscripten, EmCPython и т.д. empython.js составляет 5,8 МБ (2,1 МБ после gzip -6), без stdlib.
  3. Микропифон: это вилка.

    Там не было встроенного файла 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 МБ (225 КБ после 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, чтобы увидеть, как использовать эти файлы.

    Таким образом, вы также можете потенциально собрать PyPy и CPython в WebAssembly для интерпретации вашего приложения Python в совместимом браузере.

Другая потенциально интересная вещь здесь - это Nuitka, компилятор Python to C++. Потенциально можно собрать приложение Python для C++, а затем скомпилировать его вместе с CPython с Emscripten. Но практически я не знаю, как это сделать.

Решения

В настоящее время, если вы создаете обычный веб-сайт или веб-приложение, где скачивание JS файла размером в несколько мегабайт едва ли является опцией, обратите внимание на реализации конвейеров Python-to -j avaScript (например, Transcrypt) или JavaScript Python ( например, Brython). Или попытайте счастья с другими из списка языков, которые компилируются в JavaScript.

В противном случае, если размер загрузки не является проблемой, и вы готовы решить множество неровностей, выберите один из трех вариантов выше.

Ответ 2

Это будет невозможно, пока веб-сборка не осуществит сборку мусора. Вы можете следить за прогрессом здесь: https://github.com/WebAssembly/proposals/issues/16

Ответ 3

Вкратце: вы не можете преобразовать произвольный Python в веб-сборку, и я сомневаюсь, что вы сможете надолго. Обходной путь может быть от Python до C к веб-сборке, но обычно это не работает, поскольку Python-to-C является хрупким (см. Ниже).

WebAssembly специально ориентирована на C-подобные языки, как вы можете видеть на http://webassembly.org/docs/high-level-goals/

Перевод с Python на C может выполняться с помощью таких инструментов, как PyPy, который находится в разработке в течение длительного времени, но который все еще не работает для произвольного кода Python. Для этого есть несколько причин:

1) Python имеет очень удобные, абстрактные и приятные структуры данных, но их сложно перевести в статический код. 2) Python зависит от динамической сборки мусора. 2) Большинство Python-кодов сильно зависят от разных библиотек, каждый из которых имеет свои собственные причуды и проблемы (например, написанные на C или даже ассемблере).

Если вы посмотрите более внимательно на то, почему Python-to-C (или Python на С++) было настолько сложным, вы можете увидеть подробные причины этого краткого ответа, но я думаю, что это выходит за рамки вашего вопроса.