Encapsulando Python en un binario

Python — Sábado 24 de Septiembre de 2011, 17:00


Este es un lindo truquito que no es de mi autoría, sino que es de John Lenton (él lo mostró en una reunión del laburo), pero como yo ya lo mostré en PyCon Brasil el año pasado, y en PyCon Argentina ayer, lo pongo acá para el que lo quiera mirar...

Arrancamos con nuestro programa o proyecto Python que queremos meter adentro del binario... para nuestro ejemplo acá, crearemos un directorio, lo hacemos paquete de Python, y adentro creamos lo que sería el programa principal de nuestro sistema, con una función adentro que es la que arrancaría todo...

facundo@exopus:~/prueba$ mkdir proyecto
facundo@exopus:~/prueba$ cd proyecto/
facundo@exopus:~/prueba/proyecto$ touch __init__.py
facundo@exopus:~/prueba/proyecto$ cat principal.py
def run():
    print "Arrancamos!"
facundo@exopus:~/prueba/proyecto$ cd ..
facundo@exopus:~/prueba$

Tenemos que probar que podamos arrancar nuestro sistema desde el directorio padre... a veces no es tan fácil, hay que jugar un poquito con los paths de dónde importamos cosas, pero en este ejemplo es sencillo. Pero podemos probarlo facilmente:

facundo@exopus:~/prueba$ python
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24)
...
>>> import proyecto.principal
>>> proyecto.principal.run()
Arrancamos!
>>>

Una vez que lo logremos ejecutar así, tenemos que  poner ese mismo código en un archivo con nombre __main__.py en el directorio padre de nuestro proyecto:

facundo@exopus:~/prueba$ cat __main__.py
import proyecto.principal
proyecto.principal.run()

Volvemos a probar que nuestro sistema funciona correctamente:

facundo@exopus:~/prueba$ python __main__.py
Arrancamos!

El próximo paso es meter todo adentro de un archivo ZIP, aprovechando que Python es capaz de interpretar directamente este tipo de archivos comprimidos (por eso el nombre especial de antes, para que Python lo reconozca):

facundo@exopus:~/prueba$ zip -r proyecto.zip __main__.py proyecto/
  adding: __main__.py (deflated 27%)
  adding: proyecto/ (stored 0%)
  adding: proyecto/__init__.py (stored 0%)
  adding: proyecto/principal.pyc (deflated 45%)
  adding: proyecto/__init__.pyc (deflated 30%)
  adding: proyecto/principal.py (stored 0%)

Probamos nuevamente que, hasta acá, funcione todo correctamente:

facundo@exopus:~/prueba$ python proyecto.zip
Arrancamos!

Finalmente, metemos todo eso adentro de un binario, indicando que se va a interpretar con Python, y haciéndolo ejecutable:

facundo@exopus:~/prueba$ ( echo '#!/usr/bin/env python'; cat proyecto.zip ) > miproyecto
facundo@exopus:~/prueba$ chmod +x miproyecto

¡Ya está! Ahora podemos ejecutar ese binario, como cualquier otro binario, y realmente estaremos ejecutando nuestro proyecto Python:

facundo@exopus:~/prueba$ ./miproyecto
Arrancamos!

Genial, :)


Firefox

comentarios

  1. Gracias por compartirlo!!! En PyConAr2011 me dijiste que esto era bueno para iniciar conversaciones en los boliches, veré si me funciona!!!

    Escrito por Juan S. Bokser — 26 Sep 2011, 09:53

  2. En Windows también funciona. En lugar del último paso (crear un binario ejecutable) hay que renombrar el .zip como .py y ya está.

    Como la mayoría de las chicas usa Windows, sabiendo ese detalle ganás seguro ;)

    Escrito por Gabriel — 26 Sep 2011, 14:01

  3. Cuando lei el titulo pense que por binario te referias a un archivo que no requiere el interprete python para correr, lo cual creo que es imposible... no?

    Escrito por Flor — 27 Sep 2011, 20:35

  4. Flor: al ser Python interpretado, la forma de meterlo en un binario "auto ejecutable" es meter tu programa y el runtime de Python adentro del mismo binario (es el mismo truco que hace Visual Basic, por ejemplo).

    Si querés investigar por ese lado, buscá "py2exe".

    Slds.

    Escrito por Facundo Batista — 27 Sep 2011, 22:10

  5. No sabia que py2exe hacia eso...
    De todas formas mi necesidad apunta mas a entornos Unix/Linux...
    Hay algo similar a py2exe para estos OS? Sin caer en un instalador tipo .deb.
    Quizas estoy pidiendo demasiado... :)

    Escrito por Flor — 29 Sep 2011, 21:29

  6. Flor: en entornos Linux/Unix no es normal armar binarios con el intérprete adentro, ya que siempre tenemos Python instalado.

    Sí, podés llegar a querer empaquetar una versión particular, más bibliotecas, etc, pero no es lo que normalmente se hace: para esto están los administradores de paquetes de cada sistema operativo (que manejan los .deb, .rpm, etc), y de última tenés también PyPI, para instalar con easyinstall.

    De cualquier manera, depende mucho de lo que estés buscando hacer. Te invito a que te pases por el canal de IRC de Python Argentina (#pyar, en Freenode) y consultes allí, o mandes un mail a la lista (instrucciones aquí: http://python.com.ar/pyar/ListaDeCorreo ).

    Slds.

    Escrito por Facundo Batista — 29 Sep 2011, 23:02

  7. Yo antes lo usaba asi, podes importar desde .zip directamente, pero hoy dia uso nuitka directamente, compilo el python a binario.

    Escrito por juancarlospaco — 23 Nov 2012, 20:02


Añadir comentario

authimage






Powered by LifeType