[pyar] ¿Existe algo asi como un "compilador" Python?

fisa fisadev en gmail.com
Jue Abr 24 18:36:24 ART 2014


El día 24 de abril de 2014, 12:12, Ariel Palazzesi
<arielpalazzesi en gmail.com> escribió:
> Hola!
> Como saben, recien estoy empezando a hacer algunas cosas en Python,
> generalmente tonterias para ejecutar desde la consola de Linux.
>
> Veo que hay aplicaciones enormes y complejas hechas con este lenguaje, y me
> pregunto ¿Hay algun compilador para el?  O siempre se interpreta?
>
> Saludos, y perdón por la preguntonta.
>

Buenas! Después de ver el thread, me parece que suma que me tome el
trabajo de armar una respuesta bien completa.
Va a ser larga, pero probablemente te sepa para conocer un poco mejor
algunas cosas útiles.
Y voy a ir diciendo cosas no tan correctas, y de a poco corrigiéndome
a medida que avanzo. Pero bienvenidas las lecturas de los que saben
más como para indicarme si le erro feo en algo.

Tradicionalmente en la univ te enseñan que hay dos tipos de lenguajes:
compilados e interpretados. Y la explicación de cómo funciona cada uno
es algo que se parece a esto:

Lenguaje compilado:
1) Escribo código.
2) Una sola vez (y eso es importante) lo *compilo*, con un compilador,
y eso me genera un binario.
3) El binario es ejecutado todas las veces que quiero usar el programa.

Lenguaje interpretado:
1) Escribo código.
2) *Cada vez que ejecuto mi programa* (y eso es importante) un
intérprete genera instrucciones binarias y las ejecuta a partir de
leer mi código.

En esta explicación hay algunas cosas que no quedan muy claras. Por
ejemplo: qué es "binario"? No existe tal cosa como un código de
instrucciones en binario que sea universal y que se ejecute
directamente sobre cualquier procesador. Hay varias arquitecturas, y
normalmente uno no va directo al micro, sino que interactúa con cosas
que están en el medio (especialmente el sistema operativo). Pero
bueno, por ahora dejamos esas cosas de lado, no son las que más me
interesan.
Para los ejemplos voy a seguir hablando de "binarios" como lo que
"finalmente se ejecuta en el procesador", sin tener en cuenta si en
realidad hay alguna capa intermedia del sistema operativo y demás.

Primer cosa que sí interesa: el límite entre esos dos tipos de
lenguajes ya es borroso.
Por ejemplo, qué pasa si mi intérprete guarda las instrucciones
binarias generadas en alguna especie de caché, y las reutiliza la
próxima vez que ejecuto mi programa? No sería casi lo mismo que un
compilador? Porque hace la traducción una sola vez, y después ejecuta
esos binarios.
Es buena pregunta para hacerle al profe ;)

Pero se pone un poco más interesante cuando miramos a lo que hacen
lenguajes más nuevos como java, python, c#, ruby, etc.

Agarremos primero java y C#. De qué tipo son? La mayoría seguro
respondería que son compilados. Pero en realidad no tienen esos 3
pasos que vimos antes, sino que hacen algo parecido, algo como esto:
1) Escribo código.
2) *Una sola vez* lo compilo, con un compilador, pero no a binario!
Compilo a un archivo con código "intermedio", parecido al binario,
pero de un cachito más alto nivel.
3) *Cada vez que ejecuto mi programa*, la máquina virtual o runtime
del lenguaje, va leyendo ese código intermedio, generando
instrucciones binarias y las ejecuta.

Es eso un lenguaje compilado o un lenguaje interpretado? Tiene un poco
de cada cosa: compila a un lenguaje intermedio, que después
interpreta.
Ese lenguaje intermedio es "casi" un binario, eso seguro, y por eso la
mayoría te va a decir que son lenguajes compilados. Pero no se puede
negar que necesita del runtime para poder ejecutar (traducir) ese
intermedio a un binario de verdad, algo que es prácticamente un
intérprete (lee un lenguaje, genera binario, en tiempo de ejecución).

Y python qué hace?
Hace casi casi casi lo mismo! con una sola diferencia:
En java o C# el desarrollador hace el paso 2 como un paso específico.
En tu IDE hacés click en "compilar", o algo similar.
En Python ese paso se hace solo (automágicamente) la primera vez que
intentás ejecutar tu código.

Tanto en java como en python tenemos esa compilación a código
intermedio que sucede una sola vez, y luego la interpretación de ese
pre-compilado usando un runtime.
La diferencia está en que en java vos tenés que hacer el primer paso
manualmente, y en python se hace solo en la primer ejecución.

Y si lo pienso un poco, estoy casi seguro que la gente le dice
"compilado" a java o c# solamente porque tienen que hacer ese paso a
mano, si se lo hiciese solo el runtime al ejecutar la primera vez, no
se si les dirían "compilados".

Y ahora a complicarla un poco más:

Hay una sola forma de ejecutar python?
No, hay varias, ya te comentaron que hay unos cuantos "compiladores" de python.
Cuando la gente habla de python por lo general se refiere al
intérprete oficial, que es CPython (no confundir con Cython). Lo que
yo expliqué hasta recién es el comportamiento de *ese* intérprete.

Y el resto hacen lo mismo? O sea, tienen los mismos pasos de los que
hablábamos recién?
Nop. Por ejemplo PyPy hace algo más complicado (que no voy a explicar
acá). Jython o IronPython también tienen sus diferencias. Etc.
Así que si ya era complicado decidir si python era "compilado" o
"interpretado", imaginate ahora sabiendo que hay muchas formas
distintas de ejecutarlo.

Y para cerrar, algunas ideas sueltas más referidas al tema de
velocidad, que era el origen de tu pregunta.

* Estas diferencias en modo de ejecutar por lo general no son las que
van a hacer que tu programa sea más rápido o lento. El tema está más
del lado de qué tan bueno o qué cosas optimiza el runtime, y no
depende del momento en que hagas la compilación al intermedio. Por
ejemplo, PyPy hace cosas muy interesantes para que el runtime ejecute
algunas cosas *mucho* más rápido que el intérprete oficial.

* El tamaño de un programa tampoco es para nada un indicador de si va
a ser lento o no. La velocidad es una cosa que depende más de la
calidad y cosas que hace el código, y muy poco de que cuánto código
es. Así que no te guíes con esa regla de que si es un sistema
"grande", necesita un intérprete más rápido, porque el tamaño no es
buena medida. Por ejemplo: un script muy chico de 50 lineas que haga
algo de machine learning puede ser terriblemente más pesado en uso de
cpu que un sistema de gestión de 300.000 lineas.

* Y la velocidad de ejecución del código en sí tampoco suele ser un
factor determinante en la velocidad de ese tipo de sistemas, donde la
mayor parte del tiempo se consume en esperas de red, IO, etc
(interacciones con la base de datos, con otros sistemas,...). Así que
en tanto no vas que específicamente el código de algo sea lo lento, y
no disco, red, etc, ni vale la pena ponerse a optimizar el código. La
mayoría de las veces podés sacar mucha más ganancia con cosas como que
la db use más ram, o meter algún tipo de caché.


Saludos!

-- 
fisa  -  Juan Pedro Fisanotti


More information about the pyar mailing list