Compilazione di Python in WebAssembly


95

Ho letto che è possibile convertire il codice Python 2.7 in Web Assembly, ma non riesco a trovare una guida definitiva su come farlo.

Finora ho compilato un programma C per Web Assembly utilizzando Emscripten e tutti i suoi componenti necessari, quindi so che funziona (guida utilizzata: http://webassembly.org/getting-started/developers-guide/ )

Quali sono i passaggi che devo eseguire per farlo su una macchina Ubuntu? Devo convertire il codice python in bitcode LLVM e poi compilarlo usando Emscripten? In tal caso, come potrei ottenere questo risultato?



1
Controlla pyodide: hacks.mozilla.org/2019/04/…
Alex

1
Pyodide porta il runtime Python nel browser tramite WebAssembly: github.com/iodide-project/pyodide
guettli

Risposte:


149

WebAssembly contro asm.js

Innanzitutto, diamo un'occhiata a come, in linea di principio, WebAssembly è diverso da asm.js e se esiste il potenziale per riutilizzare le conoscenze e gli strumenti esistenti. Quanto segue fornisce una panoramica abbastanza buona:

Ricapitoliamo, WebAssembly (MVP, poiché c'è di più sulla sua roadmap , più o meno):

  • è un formato binario di AST con tipizzazione statica, che può essere eseguito da motori JavaScript esistenti (e quindi AOT compilato o compatibile con JIT),
  • è del 10-20% più compatto (confronto con gzip) e un ordine di grandezza più veloce da analizzare rispetto a JavaScript,
  • può esprimere più operazioni di basso livello che non si adattano alla sintassi JavaScript, leggere asm.js (es. interi a 64 bit, istruzioni speciali per CPU, SIMD, ecc.)
  • è convertibile (in una certa misura) in / da asm.js.

Pertanto, attualmente WebAssembly è un'iterazione su asm.js e si rivolge solo a C / C ++ (e linguaggi simili).

Python sul Web

Non sembra che GC sia l'unica cosa che impedisce al codice Python di prendere di mira WebAssembly / asm.js. Entrambi rappresentano codice di basso livello tipizzato staticamente, in cui il codice Python non può (realisticamente) essere rappresentato. Poiché l'attuale toolchain di WebAssembly / asm.js è basato su LLVM, un linguaggio che può essere facilmente compilato in LLVM IR può essere convertito in WebAssembly / asm.js. Ma ahimè, Python è troppo dinamico per adattarsi anche a esso, come dimostrato da Unladen Swallow e diversi tentativi di PyPy.

Questa presentazione di asm.js contiene diapositive sullo stato dei linguaggi dinamici . Ciò significa che attualmente è possibile solo compilare l'intera VM (implementazione del linguaggio in C / C ++) in WebAssembly / asm.js e interpretare (con JIT dove possibile) fonti originali. Per Python ci sono diversi progetti esistenti:

  1. PyPy: PyPy.js ( discorso dell'autore a PyCon ). Ecco il repo di rilascio . Il file JS principale ,, pypyjs.vm.jsè 13 MB (2 MB dopo gzip -6) + stdlib Python + altre cose.

  2. CPython: pyodide , EmPython , CPython-Emscripten , EmCPython , ecc. empython.jsÈ di 5,8 MB (2,1 MB dopo gzip -6), nessuno stdlib.

  3. Micropython: questo fork .

    Non c'era alcun file JS trzeci/emscripten/compilato lì, quindi sono stato in grado di crearlo con una toolchain Emscripten già pronta. Qualcosa di simile a:

     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 
    

    Produce micropython.js1,1 MB (225 KB dopo gzip -d). Quest'ultimo è già qualcosa da considerare, se hai bisogno solo di un'implementazione molto conforme senza stdlib.

    Per produrre WebAssembly build è possibile modificare la riga 13 del Makefilea

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

    Quindi make -jproduce:

     113 KB micropython.js
     240 KB micropython.wasm
    

    Puoi guardare l'output HTML di emcc hello.c -s WASM=1 -o hello.html, per vedere come usare questi file.

    In questo modo puoi anche potenzialmente creare PyPy e CPython in WebAssembly per interpretare la tua applicazione Python in un browser conforme.

Un'altra cosa potenzialmente interessante qui è Nuitka , un compilatore da Python a C ++. Potenzialmente può essere possibile costruire la tua app Python in C ++ e quindi compilarla insieme a CPython con Emscripten. Ma praticamente non ho idea di come farlo.

Soluzioni

Per il momento, se stai realizzando un sito web convenzionale o un'app web in cui scaricare un file JS da diversi megabyte è a malapena un'opzione, dai un'occhiata ai transpilers da Python a JavaScript (ad esempio Transcrypt ) o alle implementazioni JavaScript Python (ad esempio Brython ). Oppure tenta la fortuna con altri dall'elenco dei linguaggi che si compilano in JavaScript .

Altrimenti, se la dimensione del download non è un problema e sei pronto per affrontare molti bordi irregolari, scegli tra i tre sopra.

Aggiornamento Q3 2020

  1. La porta JavaScript è stata integrata in MicroPython. Vive in port / javascript .

  2. Il port è disponibile come pacchetto npm chiamato MicroPython.js . Puoi provarlo in RunKit .

  3. C'è un'implementazione Python sviluppata attivamente in Rust, chiamata RustPython . Poiché Rust supporta ufficialmente WebAssembly come destinazione della compilazione , non sorprende che ci sia un collegamento demo proprio all'inizio del file readme. Tuttavia, è presto. Segue il loro disclaimer.

    RustPython è in una fase di sviluppo e non dovrebbe essere utilizzato in produzione o in un ambiente intollerante ai guasti.

    La nostra build attuale supporta solo un sottoinsieme della sintassi Python.


2
Quelle dimensioni .js e .wasm non sono davvero giuste. La compressione del flusso è ben supportata e potrebbe essere utilizzata per ridurre le dimensioni di entrambi. Quanto sono grandi gli stessi file compressi con gzip? A parte questo, buona risposta.
EnigmaticPhysicist

Quindi volevo aggiungere che nel 2020, sembra che il pioduro sia la cosa più vicina che OP sta cercando. È il runtime Python nell'assemblaggio web (presumo che put C e poi Python in wasm). Supporta anche più librerie. Inoltre, sembra abbastanza facile da usare.
David Frick

3

Ciò non sarà possibile fino a quando il web assembly non implementa la garbage collection. Puoi seguire i progressi qui: https://github.com/WebAssembly/proposals/issues/16


18
Non necessariamente. Puoi implementare GC, e in particolare il conteggio dei riferimenti, poiché viene utilizzato da Python IIRC, su Wasm. In linea di principio, dovresti essere in grado di prendere CPython e compilarlo su Wasm usando Emscripten.
Andreas Rossberg

1
La mia opinione da OP era che volevano utilizzare gli strumenti esistenti - l'implementazione di cpython GC su wasm suona come un progetto in sé
Malcolm White

3
Non dovresti fare nulla in più, basta compilare CPython. Contiene già l'implementazione RC, AFAICT.
Andreas Rossberg

3

In breve: ci sono transpiler, ma non puoi convertire automaticamente alcun Python arbitrario in Web Assembly, e dubito che sarai in grado di farlo per molto tempo a venire. Sebbene teoricamente i linguaggi siano ugualmente potenti e la traduzione manuale sia sempre possibile, Python consente alcune strutture dati e modalità espressive che richiedono un compilatore (o transpiler) inter-linguaggio molto intelligente [vedi sotto]. Una soluzione alternativa potrebbe essere Python to C to Web Assembly poiché la tecnologia python-to-C è moderatamente matura, ma generalmente non funzionerà poiché anche Python-to-C è fragile (vedi sotto).

WebAssembly è specificamente mirato a linguaggi simili a C, come puoi vedere su http://webassembly.org/docs/high-level-goals/

La traduzione da Python a C può essere eseguita con strumenti come PyPy, che è in fase di sviluppo da molto tempo, ma che ancora non funziona per codice Python arbitrario. Ci sono diverse ragioni per questo:

  1. Python ha alcune strutture dati molto utili, astratte e piacevoli, ma sono difficili da tradurre in codice statico.
  2. Python dipende dalla raccolta dinamica dei rifiuti.
  3. La maggior parte del codice Python dipende in gran parte da varie librerie, ognuna delle quali ha le proprie peculiarità e problemi (come l'essere scritto in C, o anche l'assembler).

Se guardi più attentamente perché Python-to-C (o Python to C ++) è stato così complicato, puoi vedere le ragioni dettagliate dietro questa risposta concisa, ma penso che sia al di fuori dello scopo della tua domanda.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.