Компіляція Python до WebAssembly


90

Я прочитав, що можна перетворити код Python 2.7 у Web Assembly, але я не можу знайти остаточного посібника щодо того, як це зробити.

Наразі я скомпілював програму C для Web Assembly за допомогою Emscripten та усіх необхідних компонентів, тому знаю, що вона працює (використано керівництво: http://webassembly.org/getting-started/developers-guide/ )

Які кроки я повинен зробити, щоб зробити це на машині Ubuntu? Чи потрібно перетворювати код python у бітовий код LLVM, а потім компілювати його за допомогою Emscripten? Якщо так, то як би я цього досягти?




1
Pyodide передає час роботи Python до браузера через WebAssembly: github.com/iodide-project/pyodide
guettli

Відповіді:


146

WebAssembly проти asm.js

По-перше, давайте подивимося, чим, в принципі, WebAssembly відрізняється від asm.js , і чи існує потенціал для повторного використання наявних знань та інструментів. Далі подано досить хороший огляд:

Давайте рекапітулюємо WebAssembly (MVP, оскільки в дорожній карті приблизно є більше):

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

Таким чином, на даний момент WebAssembly є ітерацією на asm.js і націлена лише на C / C ++ (та подібні мови).

Python в Інтернеті

Схоже, GC - це єдине, що перешкоджає коду Python націлюватися на WebAssembly / asm.js. Обидва вони представляють низькорівневий статично набраний код, в якому код Python не може (реально) бути представлений. Оскільки поточний набір інструментів WebAssembly / asm.js базується на LLVM, мова, яка може бути легко скомпільована до LLVM IR, може бути перетворена на 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: піодид , 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.js1,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 на C ++. Потенційно можливо створити програму Python на C ++, а потім скомпілювати її разом із CPython за допомогою Emscripten. Але я практично не уявляю, як це зробити.

Рішення

На даний момент, якщо ви створюєте звичайний веб-сайт або веб-програму, де завантаження файлу JS на декілька мегабайт ледве можливо, подивіться на транпілятори Python-to-JavaScript (наприклад, Transcrypt ) або реалізації JavaScript Python (наприклад, Brython ). Або спробуйте свою удачу з іншими зі списку мов, які компілюються на JavaScript .

В іншому випадку, якщо розмір завантаження не є проблемою, і ви готові вирішити багато нерівних країв, виберіть один із трьох варіантів.

Оновлення Q3 2020

  1. Порт JavaScript був інтегрований в MicroPython. Він живе в портах / javascript .

  2. Порт доступний як пакет npm під назвою MicroPython.js . Ви можете спробувати це в RunKit .

  3. У Rust активно розробляється реалізація Python, яка називається RustPython . Оскільки Rust офіційно підтримує WebAssembly як ціль компіляції , не дивно, що демонстраційне посилання знаходиться у верхній частині readme. Хоча рано. Далі йдеться про їх застереження.

    RustPython перебуває на стадії розробки, і його не слід використовувати у виробництві або в умовах непереносимості несправностей.

    Наша поточна збірка підтримує лише підмножину синтаксису Python.


1
Ці розміри .js та .wasm насправді не є справедливими. Стиснення потоку добре підтримується і може бути використано для зменшення розміру обох. Наскільки великі однакові файли, зішпатовані в архіві? Крім цього, хороша відповідь.
enigmaticPhysicist

Тому хотів додати, що в 2020 році, здається, піодид - це найближче, що шукає ОП. Це час роботи Python у веб-збірці (я б припустив, що кладе C, а потім Python у wasm). Він також підтримує кілька бібліотек. Крім того, здається досить простим у використанні.
Девід Фрік,

3

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


17
Не обов'язково. Ви можете реалізувати GC - і особливо підрахунок посилань, як це використовується Python IIRC - поверх Wasm. В принципі, ви повинні мати можливість взяти CPython і скомпілювати його в Wasm за допомогою Emscripten.
Андреас Росберг,

1
Я висловив думку з OP, що вони хотіли використовувати існуючі інструменти - реалізація cpython GC поверх wasm звучить як проект сам по собі
Malcolm White

3
Вам не потрібно робити нічого зайвого, просто отримайте CPython для компіляції. Він уже містить реалізацію RC, AFAICT.
Андреас Росберг,

3

Коротше кажучи: Є транпілятори, але ви не можете автоматично перетворити будь-який довільний Python на Web Assembly, і я сумніваюся, що ви зможете це зробити ще довго. Хоча теоретично мови однаково потужні, і ручний переклад завжди можливий, Python допускає деякі структури даних та виразні режими, що вимагає дуже розумного міжмовного компілятора (або транпілятора) [див. Нижче]. Обхідним шляхом може бути Python до C до Web Assembly, оскільки технологія python-to-C поміркована, але це, як правило, також не спрацює, оскільки Python-to-C також неміцний (див. Нижче).

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

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

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

Якщо ви уважніше вивчите, чому Python-to-C (або Python до C ++) був настільки хитрим, ви зможете побачити детальні причини цієї короткої відповіді, але я думаю, що це виходить за рамки вашого запитання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.