Python en el navegador: ¿Cómo elegir entre Brython, PyPy.js, Skulpt y Transcrypt?
browser (7)
Estoy muy emocionado de ver que ahora es posible codificar Python en el navegador. Estos son los principales candidatos (agregue los que haya pasado por alto):
¿Pero cómo elegir entre ellos? La única diferencia obvia que puedo ver es que Skulpt se basa en Python 2, mientras que Brython se basa en Python 3.
Tenga en cuenta: Esta no es una solicitud de recomendaciones u opiniones. Estoy buscando hechos objetivos que informarían una elección educada.
Aquí hay información sobre Brython vs Transcrypt (julio de 2016, ya que Transcrypt fue agregado como una opción en esta pregunta por parte del OP), obtenida al comenzar un proyecto con Brython hace unos meses y mudarse a Transcrypt (completado la semana pasada). Me gustan Brython y Transcrypt y puedo ver usos para ambos.
Para las personas que son nuevas en esto, Brython y Transcrypt ''transpilan'' la entrada de Python a javascript (Editar: tal vez sea mejor ver a Brython como ''una implementación de Python para el navegador'' porque no produce javascript independiente). Ambos requieren la sintaxis de Python 3. Brython incluye una cantidad sustancial de bibliotecas estándar de Python y algunas propias para tratar asuntos relacionados con la web, mientras que Transcrypt evita eso en su mayor parte y sugiere usar bibliotecas Javascript en su lugar.
Brython ( Github ) puede hacer la conversión en el navegador. Entonces escribe en python y el motor brython.js lo convierte a JavaScript sobre la marcha cuando se carga la página. Esto es realmente conveniente y es mucho más rápido de lo que piensas. Sin embargo, el motor brython.js que necesita incluir en sus páginas es de aproximadamente 500Kb. Además, está la cuestión de importar bibliotecas estándar, que Brython maneja recuperando archivos .js separados con solicitudes XHR. Algunas bibliotecas ya están compiladas en brython.js, por lo que no todas las importaciones atraerán nuevos archivos, pero si usa muchas importaciones, las cosas pueden volverse lentas. Sin embargo, hay formas de evitar esto. Lo que hice fue verificar la pestaña de red en las herramientas de desarrollo del navegador para ver qué archivos se estaban extrayendo cuando se cargó la página, luego eliminar todos los archivos que mi proyecto no estaba usando en una copia de la carpeta Brython src y ejecutar el script incluido con Brython (creo que está en Brython / www / scripts / make_VFS.py) que compila todas las bibliotecas disponibles en un archivo llamado py_VFS.js al que también debe vincular desde su html. Normalmente, creará un gran archivo de 2 MB +, pero si elimina las cosas que no está usando, puede ser bastante pequeño. Hacerlo de esta manera significa que solo necesita ingresar brython.js, py_VFS.js y su código de python, y no se necesitarán solicitudes XHR adicionales.
Transcrypt ( Github ), por otro lado, se distribuye como un paquete de python 3 que puede usar manualmente, o enganchar en su cadena de herramientas, para compilar python a javascript por adelantado. Entonces, con Transcrypt, escribe en python, ejecuta transcrypt contra python y escupe javascript que puede vincular en su proyecto. Se parece más a un compilador tradicional también porque ofrece cierto control sobre la salida. Por ejemplo, puede optar por compilar a ES6 o ES5, o pedirle que envíe mapas de origen (que durante la depuración, el navegador lo llevará directamente al código de Python correspondiente, en lugar del código de JavaScript generado). La salida de JavaScript de Transcrypt es bastante breve ( o dicho de otra manera, es bonito y conciso). En mi caso, 150kB de python se convierten en 165kB de javascript ES5 sin minificar. A modo de comparación, la versión Brython de mi proyecto usó aproximadamente 800Kb después de la conversión.
Sin embargo, obtener los beneficios de la brevedad de Transcrypts requiere leer un poco los documentos (realmente solo un poco). Por ejemplo, con Transcrypt, la ''veracidad'' de Python para estructuras de datos como dict, set and list no está habilitada de manera predeterminada y no se habilita a nivel global debido a posibles problemas de rendimiento relacionados con la verificación de tipos. Para mayor claridad: en CPython, un dict vacío, conjunto o lista tiene un valor de verdad Falso, mientras que en Javascript se considera ''verdadero''. Ejemplo:
myList = []
if myList: # False in CPython bcs it''s empty, true in javascript bcs it exists
# do some things.
Hay al menos tres formas de abordar esto:
- Use el indicador -t al convertir python a javascript, por ejemplo: $ transcrypt -t python.py (no recomendado, pero probablemente no sea un problema a menos que verifique la veracidad muchas veces en los bucles internos del código sensible al rendimiento ...)
-
Use
__pragma__(tconv)
o__pragma__(notconv)
dentro de su código para decirle al compilador de transcriptos que active la conversión automática a valores de verdad similares a python localmente. - En lugar de verificar el valor de verdad, evite el problema del todo simplemente marcando len (myList)> 0 ... Tal vez eso esté bien para la mayoría de las situaciones, hace el trabajo para mi uso ligero.
Correcto, así que mi proyecto se estaba haciendo más grande y quería precompilar para obtener un aumento de rendimiento, pero me resultó difícil hacerlo con Brython (aunque es técnicamente posible, una manera fácil es usar el editor en línea y hacer clic en el botón de JavaScript para ver La salida). Lo hice y me vinculé al javascript generado desde project.html pero no funcionó por alguna razón. Además, me resulta difícil entender los mensajes de error de Brython, así que no sabía por dónde empezar después de que este paso fallara. Además, el gran tamaño del código de salida y el tamaño del motor brython comenzaba a molestarme. Así que decidí echar un vistazo más de cerca a Transcrypt, que al principio parecía tener una calificación más alta porque prefiero instrucciones tontas que me dicen cómo comenzar de inmediato (desde entonces se han agregado).
Lo principal para configurarlo después de instalar Python3.5 fue:
- Use venv (es como una nueva versión incorporada de virtualenv que usa menos espacio para cada proyecto) para configurar una carpeta de proyecto python3.5 (solo escriba: python3.5 -m venv foldername - solución para ubuntu con problemas de paquete para 3.5 ) Esto hace ''nombre de carpeta'' con una subcarpeta bin entre otras cosas.
- Instale el paquete Python Transcrypt con pip (''nombre de carpeta / bin / pip install transcrypt'') que lo instala en foldername / lib / python3.5 / site-packages / transcrypt.
-
activate
el terminal actual si no desea tener que escribir la ruta completa a foldername / bin / python3.5 cada vez. Activar escribiendo: ''nombre de carpeta de origen / bin / activar'' -
Comience a escribir código y compilarlo en JavaScript para realizar pruebas.
Compile desde la carpeta en la que escribe su código. Por ejemplo, usé foldername / www / project.
Entonces CD en esa carpeta y ejecute: ''transcrypt -b your_python_script.py''.
Eso coloca la salida en una subcarpeta llamada
__javascript__
. Luego puede vincular al javascript generado desde su html.
Principales problemas que se mueven
Tengo necesidades bastante simples, por lo que su kilometraje puede variar.
-
Debe reemplazar las bibliotecas estándar de brython o python con las bibliotecas javascript. Entonces, por ejemplo, Brython proporciona ''import json'', pero en Transcrypt puede usar una lib javascript o simplemente usar JSON.parse / JSON.stringify directamente en su código Python. Para incluir una versión reducida de una biblioteca de JavaScript directamente en su código de Python, use este formato (tenga en cuenta las comillas triples):
__pragma__ (''js'', ''{}'', '''''' // javascript code '''''')
-
Las funciones específicas html de Brython no funcionan con Transcrypt obviamente. Solo usa las formas normales de javascript. Ejemplos: 1) en Brython, es posible que haya hecho referencia a una etiqueta HTML específica usando ''document ['' id '']'', pero con Transcrypt usaría ''document.getElementById ('' id '') (que es de la misma manera que lo hace) desde javascript). 2) No puede eliminar un nodo con ''del nodeName'' (bcs que es una función de brython). Use algo como ''node.parentNode.removeChild (node)''. 3) reemplace todas las funciones DOM de brython con las alternativas de javascript. por ejemplo, class_name = className; text = textContent; html = innerHTML; parent = parentNode; children = childNodes, etc. Supongo que si necesita algo que contenga alternativas requeridas por algunos navegadores antiguos, existen bibliotecas javascript para eso. 4) El set_timeout de Brython se reemplaza con javascripts setTimeout 5) Las etiquetas html de Brython como BR () deben reemplazarse utilizando las formas normales de JavaScript, así como rehacer cualquier lugar que haya utilizado su sintaxis de manipulación <= dom. Inyecte el marcado de texto sin formato como innerHTML o cree los elementos con la sintaxis de JavaScript y luego adjúntelos con la sintaxis DOM de JavaScript normal. También noté que para las casillas de verificación brython usa "if checkbox = ''check'':" pero Transcrypt está contento con "if checkbox:" ..
-
Terminé de mover un proyecto de 2700 líneas la semana pasada, momento en el que Transcrypt no tenía soporte para algunas cosas menores (aunque eran lo suficientemente fáciles de reemplazar con rellenos), estos fueron 1) str.lower, str.split (str. split está presente, pero parece ser el split de javascript, que funciona de manera diferente a la versión de python, cuyo comportamiento confiaba en), 2) round (esto parece ser compatible con la versión dev ahora) y 3) isinstance didn No trabaje en str, int y float, solo en dict, list y set. 4) Otra diferencia con respecto a Brython que noté es que si obtengo una representación JSON de un dict, debo hacerlo usando ''myDict = dict (data)'', mientras que brython estaba contento con ''myDict = data''. Pero eso podría estar relacionado con algo en json.loads de Brython, que reemplacé directamente con JSON.parse. 5) Además, sin la sobrecarga del operador Transcrypts específicamente habilitada (usando -o switch para global, o
__pragma__(''opov'')
para local), no puede hacer cosas como establecer operaciones usando el formato sobrecargado, pero necesita usar las funciones correspondientes. P.eja = set([1, 2, 3]) b = set([3, 4, 5]) a.difference(b) # is used instead of a - b a.union(b) # used instead of a | b a.intersection(b) # used instead of a & b a.symmetric_difference(b) # used instead of a ^ b
6) Además, no puede iterar dictos por defecto usando ''for i in dict:'', sin habilitar eso (cmd line -i o
__pragma__(''iconv'')
, pero puede evitar tener que habilitarlo simplemente usando las teclas () miembro, por ejemplo:
for key, value in dict.items():
# do things for each key and value..
Resumir
-
Me gusta Brython porque es fácil comenzar a usarlo y probar su código (solo F5). Está más cerca del verdadero Python porque la mayor parte de la lib estándar está ahí. No me gusta tener que incluir el motor de transpilación (Editar: O uno podría verlo como una máquina virtual de Python) en el navegador y el gran tamaño de JavaScript de salida. Si tuviera que hacer las cosas (pero aún usando Brython), habría usado métodos javascript para manipular el DOM desde brython (lo que puedes hacer ...), en lugar de depender tanto de los métodos brython porque eso desperdició el tiempo moviéndose a otro transpiler cuando mis necesidades cambiaron.
-
Me gusta Transcrypt porque el javascript generado es realmente ''simple y malo'' y porque lo único que carga en el lado del navegador es su código javascript generado, que es similar en tamaño a su código python. También porque admite mapas de origen y porque me da una medida de control sobre el javascript generado. Y usarlo me enseñó bastante sobre la optimización.
Espero que eso ayude a alguien a ver cuál de estos podría ser bueno para su proyecto en particular.
Como nadie lo ha mencionado, pensé que valía la pena mencionar a Batavia que implementa la máquina virtual Python para ejecutar el bytecode precompilado de Python.
Acabo de probarlo y, aunque es un concepto interesante, todavía está en las primeras etapas, ya que hay poca documentación.
Al final, dependerá de lo que intente hacer. Elegí Transcrypt después de echar un vistazo porque era más pragmático y de mejor rendimiento, también más recientemente lanzado / mantenido.
En primer lugar, soy un committer de Brython. Sin embargo, intentaré ser lo más imparcial posible por hacer una evaluación objetiva.
La última vez que lo usé, Skulpt no admitía características como las expresiones generadoras. Brython y PyPy.js lo hacen, por lo que en el nivel de características, en mi humilde opinión, los posteriores son superiores.
Brython (en este momento) todavía está en progreso. Algunos módulos no se pueden importar (por ejemplo, xml.ElementTree ). Sin embargo, esta situación está comenzando a cambiar ya que estamos trabajando para ejecutar todo el conjunto de pruebas de CPython a pesar de lograr una compatibilidad total con los estándares (al menos cuando tiene sentido).
Brython también admite .vfs.js para acelerar las importaciones de módulos.
PyPy.js tiene una serie de características que se deducen directamente del hecho de que funciona con PyPy (compilación JIT, bien probada, ...) pero no estoy seguro de si es adecuado para ejecutarse en el navegador. Esto podría cambiar a medida que evoluciona el proyecto.
TODO: Intentaré complementar mi respuesta con puntos de referencia confiables.
Esta es una conferencia actualizada que compara todas las opciones disponibles en el mercado en este momento:
https://www.youtube.com/watch?v=2XSeNQyPlTY
El orador es Russell Keith-Magee, un conocido desarrollador en el área.
He usado y comprometido a skulpt y pypyjs. Y son los tres muy diferentes que cualquier comparación es discutible si me preguntas.
Depende de lo que esté buscando, lo que tendrá más sentido.
PyPyJS
pypyjs es enorme, es un archivo javascript de 12MB que contiene toda la máquina virtual pypy.
Entonces, si desea completar la implementación de Python, este es su bebé.
Tiene un puente javascript que funciona muy bien, pero no es una opción viable para escribir el código de su sitio web javascript en python.
Sin embargo, le permitirá
import compiler
.
Está construido con emscripten y es más rápido que CPython, al ejecutar el benchmark pystone.
Di una breve charla sobre pypyjs here están las diapositivas.
Skulpt
Es una herramienta de enseñanza (o se ha convertido en eso con el tiempo), compila su python en una máquina de estados que emula muy estrechamente el compilador cpython. En esencia, es una implementación manuscrita del compilador de Python en JavaScript. Permite la ejecución asincrónica que le permite hacer:
while (True):
print "hi"
Sin bloquear el navegador.
Skulpt es el único que admite continuaciones asincrónicas, le permite pausar la ejecución de python mientras resuelve que suceda algo asincrónico. Haciendo que esto funcione:
from time import sleep
sleep(1)
Skulpt corre aproximadamente a una décima parte de la velocidad de CPython, al comparar pystone.
Brython
Sé menos sobre este, tal vez @ olemis-lang pueda expandir este. Pero al lado de la obvia diferencia de que Brython es py3 y los otros py2. Brython también es un transpilador.
Brython no ejecuta el benchmark pystone porque time.clock no está implementado, porque oficialmente es una función de hardware.
No se menciona aquí es RapydScript o RapydScript-NG. Producen un código JavaScript muy eficiente, que se utiliza en GlowScript VPython (glowscript.org). Solía usar el RapydScript original de Alex Tsepkov ( https://github.com/atsepkov/RapydScript ) pero recientemente cambié a RapydScript-NG de Kovid Goyal ( https://github.com/kovidgoyal/rapydscript-ng ). Recientemente ejecuté el benchmark pystone en CPython, RapydScript y Brython, y puede ver los resultados aquí:
https://groups.google.com/forum/?fromgroups&hl=en#!topic/brython/20hAC9L3ayE
Esta página compara a los tres candidatos. Brython emerge como un claro ganador.
A pesar de la "ayuda" que explica que SO no es bueno para este tipo de preguntas, parece que en este caso es posible una respuesta concisa.
¿Quizás la gente está siendo demasiado apresurada?