Compilar Python a WebAssembly
emscripten (3)
WebAssembly vs asm.js
Primero, echemos un vistazo a cómo, en principio, WebAssembly es diferente de asm.js , y si existe el potencial de reutilizar el conocimiento y las herramientas existentes. Lo siguiente ofrece una buena visión general:
- ¿Por qué crear un nuevo estándar cuando ya hay asm.js?
- ¿Cuál es la diferencia entre asm.js y el ensamblaje web?
- Por qué WebAssembly es más rápido que asm.js
Recapitulemos, WebAssembly (MVP, ya que hay más en su hoja de ruta , más o menos):
- es un formato binario de AST con tipeo estático, que puede ser ejecutado por los motores JavaScript existentes (y, por lo tanto, con capacidad JIT o AOT compilado),
- es 10-20% más compacto (comparación comprimida) y un orden de magnitud más rápido de analizar que JavaScript,
- puede expresar más operaciones de bajo nivel que no encajan en la sintaxis de JavaScript, leer asm.js (por ejemplo, enteros de 64 bits, instrucciones especiales de CPU, SIMD, etc.)
- es convertible (hasta cierto punto) a / desde asm.js.
Por lo tanto, actualmente WebAssembly es una iteración en asm.js y se dirige solo a C / C ++.
Python en la web
No parece que GC sea lo único que impida que el código Python apunte a WebAssembly / asm.js. Ambos representan código de tipo estático de bajo nivel, en el que el código de Python no puede representarse (de manera realista). Como la cadena de herramientas actual de WebAssembly / asm.js se basa en LLVM, un lenguaje que se puede compilar fácilmente en LLVM IR se puede convertir en WebAssembly / asm.js. Pero, por desgracia, Python es demasiado dinámico para encajar también en él, como lo demuestra Unladen Swallow y varios intentos de PyPy.
Esta presentación de asm.js tiene diapositivas sobre el estado de los lenguajes dinámicos . Lo que significa es que actualmente solo es posible compilar VM completa (implementación de lenguaje en C / C ++) en WebAssembly / asm.js e interpretar (con JIT donde sea posible) fuentes originales. Para Python hay varios proyectos existentes:
-
PyPy:
PyPy.js
(
charla
del autor
en PyCon
).
Aquí está el
repositorio de lanzamiento
.
El archivo JS principal,
pypyjs.vm.js
, tiene 13 MB (2 MB después degzip -6
) + Python stdlib + otras cosas. -
CPython:
pyodide
,
EmPython
,
CPython-Emscripten
,
EmCPython
, etc.
empython.js
tiene 5.8 MB (2.1 MB después degzip -6
), no stdlib. -
Micropython: este tenedor .
No había un archivo JS construido allí, así que pude construirlo con
trzeci/emscripten/
, una cadena de herramientas Emscripten lista para usar. Algo como: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.js
de 1.1 MB (225 KB después degzip -d
). Esto último ya es algo a considerar, si solo necesita una implementación muy compatible sin stdlib.Para producir la compilación de WebAssembly, puede cambiar la línea 13 del
Makefile
aCC = emcc -s RESERVED_FUNCTION_POINTERS=20 -s WASM=1
Entonces
make -j
produce:113 KB micropython.js 240 KB micropython.wasm
Puede ver la salida HTML de
emcc hello.c -s WASM=1 -o hello.html
, para ver cómo usar estos archivos.De esta forma, también puede construir PyPy y CPython en WebAssembly para interpretar su aplicación Python en un navegador compatible.
Otra cosa potencialmente interesante aquí es Nuitka , un compilador de Python a C ++. Potencialmente, puede ser posible construir su aplicación Python en C ++ y luego compilarla junto con CPython con Emscripten. Pero prácticamente no tengo idea de cómo hacerlo.
Soluciones
Por el momento, si está creando un sitio web convencional o una aplicación web donde descargar archivos JS de varios megabytes es apenas una opción, eche un vistazo a los transpiladores de Python a JavaScript (por ejemplo, Transcrypt ) o las implementaciones de JavaScript Python (por ejemplo, Brython ) O pruebe su suerte con otros de la lista de idiomas que compilan a JavaScript .
De lo contrario, si el tamaño de descarga no es un problema, y está listo para abordar muchos bordes irregulares, elija entre los tres anteriores.
He leído que es posible convertir el código Python 2.7 a Web Assembly, pero no puedo encontrar una guía definitiva sobre cómo hacerlo.
Hasta ahora he compilado un programa C para Web Assembly usando Emscripten y todos sus componentes necesarios, así que sé que está funcionando (guía utilizada: http://webassembly.org/getting-started/developers-guide/ )
¿Cuáles son los pasos que debo seguir para hacer esto en una máquina Ubuntu? ¿Tengo que convertir el código de Python a código de bits LLVM y luego compilarlo con Emscripten? Si es así, ¿cómo podría lograr esto?
En resumen: no puede convertir Python arbitrario a Web Assembly, y dudo que pueda hacerlo durante mucho tiempo. Una solución alternativa podría ser Python to C to Web Assembly, pero eso tampoco funcionará, ya que Python-to-C es frágil (ver más abajo).
WebAssembly está específicamente dirigido a lenguajes tipo C como puede ver en http://webassembly.org/docs/high-level-goals/
La traducción de Python a C se puede hacer con herramientas como PyPy, que ha estado en desarrollo durante mucho tiempo, pero que aún no funciona para el código arbitrario de Python. Hay varias razones para esto:
1) Python tiene algunas estructuras de datos muy prácticas, abstractas y agradables, pero son difíciles de traducir en código estático. 2) Python depende de la recolección dinámica de basura. 2) La mayoría del código de Python depende en gran medida de varias bibliotecas, cada una de las cuales tiene sus propias peculiaridades y problemas (como estar escrito en C, o incluso ensamblador).
Si observa más detenidamente por qué Python-to-C (o Python to C ++) ha sido tan complicado, puede ver las razones detalladas detrás de esta respuesta concisa, pero creo que está fuera del alcance de su pregunta.
Esto no será posible hasta que el ensamblaje web implemente la recolección de basura. Puede seguir el progreso aquí: https://github.com/WebAssembly/proposals/issues/16