web-dev-qa-db-fra.com

Compiler Python vers WebAssembly

J'ai lu qu'il est possible de convertir le code Python 2.7 en Web Assembly, mais je ne trouve pas de guide définitif sur la procédure à suivre.

Jusqu'ici, j'ai compilé un programme C pour Web Assembly en utilisant Emscripten et tous ses composants nécessaires. Je sais donc qu'il fonctionne (guide utilisé: http://webassembly.org/getting-started/developers-guide/ )

Quelles sont les étapes que je dois suivre pour le faire sur une machine Ubuntu? Dois-je convertir le code python en bitcode LLVM puis le compiler à l'aide de Emscripten? Si oui, comment pourrais-je y parvenir?

59
Robbie

WebAssembly vs asm.js

Tout d’abord, examinons en quoi WebAssembly est différent de asm.js , et s'il existe un potentiel de réutilisation des connaissances et des outils existants. Ce qui suit donne un bon aperçu:

Récapitulons WebAssembly (MVP, car il y en a plus sur sa feuille de route , à peu près):

  • est un format binaire de AST avec typage statique, qui peut être exécuté par les moteurs JavaScript existants (et donc par AOT compilable ou compilé),
  • il est 10-20% plus compact (comparaison gzippée) et d'un ordre de grandeur plus rapide à analyser que JavaScript,
  • il peut exprimer davantage d'opérations de bas niveau qui ne rentrent pas dans la syntaxe JavaScript, comme indiqué par asm.js (par exemple, entiers 64 bits, instructions spéciales de la CPU, SIMD, etc.)
  • est convertible (dans une certaine mesure) vers/depuis asm.js.

Ainsi, WebAssembly est actuellement une itération sur asm.js et cible uniquement C/C++.

Python sur le Web

GC ne semble pas être la seule chose qui empêche le code Python de cibler WebAssembly/asm.js. Les deux représentent un code de bas niveau typé statiquement, dans lequel le code Python ne peut pas (de manière réaliste) être représenté. La chaîne d'outils actuelle de WebAssembly/asm.js étant basée sur LLVM, un langage facilement compilable en LLVM IR peut être converti en WebAssembly/asm.js. Mais hélas, Python est trop dynamique pour y être intégré, comme le prouve nladen Swallow et plusieurs tentatives de PyPy.

Cette présentation asm.js a diapositives sur l’état des langages dynamiques . Cela signifie qu'actuellement, il n'est possible de compiler que VM (implémentation du langage en C/C++) entier vers WebAssembly/asm.js et d'interpréter (avec JIT si possible) les sources originales. Pour Python il y a plusieurs projets existants:

  1. PyPy: PyPy.js (l'auteur entretien à PyCon ). Voici release repo . Le fichier JS principal, _pypyjs.vm.js_, fait 13 Mo (2 Mo après _gzip -6_) + Python stdlib + autres éléments.
  2. CPython: pyodide , EmPython , CPython-Emscripten , EmCPython , etc. _empython.js_ est de 5,8 Mo (2,1 Mo après _gzip -6_), pas de stdlib.
  3. Micropython: cette fourche .

    Il n’existait pas de fichier JS construit, j’ai donc pu le construire avec trzeci/emscripten/ , une chaîne d’outils Emscripten prête à l’emploi. Quelque chose comme:

    _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 
    _

    Il produit _micropython.js_ de 1,1 Mo (225 Ko après _gzip -d_). Ce dernier est déjà quelque chose à considérer, si vous n'avez besoin que d'une implémentation très conforme sans stdlib.

    Pour générer WebAssembly, vous pouvez modifier la ligne 13 de la Makefile en

    _CC = emcc -s RESERVED_FUNCTION_POINTERS=20 -s WASM=1
    _

    Alors _make -j_ produit:

    _113 KB micropython.js
    240 KB micropython.wasm
    _

    Vous pouvez consulter la sortie HTML de _emcc hello.c -s WASM=1 -o hello.html_ pour voir comment utiliser ces fichiers.

    De cette manière, vous pouvez également potentiellement construire PyPy et CPython dans WebAssembly pour interpréter votre application Python dans un navigateur compatible.

Une autre chose potentiellement intéressante ici est Nuitka , un compilateur Python to C++. Potentiellement, il est possible de construire votre application Python en C++, puis de la compiler avec CPython avec Emscripten. Mais pratiquement, je n'ai aucune idée de comment le faire.

Solutions

Pour le moment, si vous construisez un site Web conventionnel ou une application Web où télécharger le fichier JS de plusieurs mégaoctets n’est guère une option, jetez un coup d’œil aux transpileurs Python-JavaScript (par exemple, Transcrypt ) ou JavaScript Python _ implémentations (par exemple, Brython ). Ou tentez votre chance avec d'autres de liste des langues compilées en JavaScript .

Sinon, si la taille du téléchargement ne pose pas de problème et que vous êtes prêt à affronter de nombreux obstacles, choisissez l’une des trois options ci-dessus.

101
saaj

En bref: vous ne pouvez pas convertir Python arbitraire en Web Assembly, et je doute que vous puissiez le faire pendant encore longtemps. Une solution de contournement pourrait être Python to C to Web Assembly, mais cela ne fonctionnera généralement pas non plus, car Python-to-C est fragile (voir ci-dessous).

WebAssembly est spécifiquement destiné aux langues de type C, comme vous pouvez le voir sur http://webassembly.org/docs/high-level-goals/

Traduire de Python en C peut être fait avec des outils tels que PyPy, qui est en développement depuis longtemps, mais qui ne fonctionne toujours pas pour le code arbitraire Python. Il y a plusieurs raisons à cela:

1) Python possède des structures de données très pratiques, abstraites et Nice, mais elles sont difficiles à traduire en code statique. 2) Python dépend de la récupération de place dynamique. 2) La plupart du code Python dépend fortement de diverses bibliothèques, chacune ayant ses propres problèmes et ses propres problèmes (comme être écrit en C ou même en assembleur).

Si vous regardez plus attentivement pourquoi Python-to-C (ou Python à C++) a été si difficile, vous pouvez voir les raisons détaillées de cette réponse laconique, mais je pense que cela sort du cadre de votre question.

4
GregD

Cela ne sera possible que lorsque Web Assembly aura implémenté la récupération de place. Vous pouvez suivre les progrès ici: https://github.com/WebAssembly/proposals/issues/16

4
Malcolm White