Estructura e instalación de proyectos en Python

Hola,

Worpress me pregunta qué estoy pensando y como siempre tengo ideas locas y homicidas en la cabeza no puedo ponerlo así que os cuento cosas de Python que hace tiempo que tengo en el tintero. Hace unos meses comencé un desarrollo de algo útil de verdad, una herramienta para el trabajo que realizaba en la empresa en la que trabajaba. Esa herramienta estaría compuesta por un cliente y un servidor, que fuesen capaces de intercambiarse mensajes. Además, el cliente tenía que tener una interfaz gráfica (si tienes que escuchar a la interfaz y a los mensajes necesitas multithreading) y el servidor tenía que hacer consultas a una base de datos.

Como era una herramienta para todos los compañeros de trabajo y cada uno tiene una distro distinta cada cual más molona (Hola Gentoo!) lo mejor era que fuese algo sencillo de instalar y que tirase de pocas dependencias. Estuvimos barajando varios lenguajes (C++, mi droga favorita) y nos decidimos por Python porque trata strings con bastante facilidad y se pueden hacer interfaces gráficas en Qt con PyQt (o PySide, pero yo usé el otro) y, sobre todo, porque no lo había usado nunca y ya estaba tardando mucho en aprenderlo.

El programa es muy sencillito, cuando se libere lo publico por aquí para comentarlo pero eso otro día.

El tema es que nunca había hecho nada en Python y no tenía ni idea de como hacer las cosas básicas así que hablo un poco de lo que aprendí ahora por si os parece molón. Para aprender leí por internet y copié bastante[1] a los chicos de Ansible, un proyecto superguapo para controlar muchos equipos a la vez (que he usado alguna vez en la empresa también). Me quedé loco en dos puntos, uno porque no sabía cómo hacerlo y el otro porque vi que se podía y me pareció superinteresante. Los comento:

El primero de ellos es la estructura de directorios del proyecto. No tenía ni idea de cómo organizarlo. Esto va muy ligado al segundo punto, que es una manera de hacer que se instale solo, así que lo explicaré un poco junto. Para instalar programas en GNU-Linux hay que fijarse en los directorios estándar… “/usr/bin”, “/usr/lib” y esas cosas. Tranquis, no voy a dar un speech porque tampoco es lo mío [2].

Python se estructura en módulos. Los módulos son los archivos de código fuente, los .py. Un paquete es un conjunto de módulos y subpaquetes. Cuando haces un import, buscas un módulo o un paquete (depende de cómo lo hagas), estos se buscan en el directorio actual o en los directorios por defecto. Que normalmente son “/usr/local/lib/python2.7” o “/usr/lib/python2.7” o la versión de Python correspondiente.

Según lo que estuve viendo, lo más fácil es crear un paquete para el programa y llamarlo desde un script cortito que estaría instalado en las carpetas habituales de los ejecutables “/usr/bin” o “/usr/local/bin”. De esta forma lo único que hay que hacer durante la instalación es colocar el paquete en un lugar y el script en otro. Como los módulos están en los sitios buenos el script es capaz de cargarlos con un import. Evidentemente, el único que necesita permisos de ejecución es el script.

Vale, esto en el árbol de directorios queda reflejado de la siguiente manera considerando un ejemplo simple:

  • Mi_Programa: Directorio general
    • bin: donde se guardan los scripts ejecutables.
      • ejecutable: lanza el programa, puede haber varios para diferentes cosas.
    • Mi_Paquete: donde se guarda el grueso del programa.
      • __init__.py: para que sepa que la carpeta es un paquete. En los casos simples el archivo está vacío pero se puede llenar de cositas.
      • *.py: nuestros archivos de código. Nuestros módulos.
    • Carpetas extra: tests y cosas así.
    • LICENSE: para la licencia, aka MANIFEST.
    • README: para nuestras cositas de developers.
    • setup.py: para instalar, una de las razones del post, lo explico más abajo.

Con esta estructura tenemos un paquete llamado Mi_Paquete que tiene el grueso del programa y un ejecutable llamado ejecutable (soy superimaginativo para los nombres, lo sé). El contenido de este último puede ser el siguiente (suponiendo que tenemos un archivo llamado main.py):

#!/usr/bin/env python

#__requires__ = ['Mi_Paquete']

from Mi_Paquete.main import main

main()

Así de fácil. Por supuesto, en el módulo tendremos que definir las funciones adecuadas, en este caso el main. Se podrían hacer varios ejecutables diferentes y que cada uno haga cosas distintas, pero el plan es que sean simples y que el código se mantenga en el módulo.

Tal y como hemos dicho antes, el ejecutable tiene que ir a “/usr/bin” o “/usr/local/bin” y el resto a “/usr/lib/python” o “/usr/local/lib/python”. Pero como ante todo somos unos vaguetes vamos a hacer que se haga sólo usando el setup.py.

El setup.py es un script que gestionará automáticamente la instalación del programa y cosas relacionadas con ello. Este es uno de ejemplo, lo más simple que se me ha ocurrido, pero debería ser completamente funcional:

from distutils.core import setup

setup(name='My_Programa',
    version='Version',
    description='Mi programa todo molón para hacer cosas to guapas',
    author='Yo',
    author_email='mi_email@email.com',
    license='Licencia',
    packages=['Mi_Paquete'],
    scripts=[
    'bin/ejecutable',
    ],
    )

Con este setup.py, si ejecutásemos “setup.py install” en la carpeta nos instalaría el programa poniendo cada cosa en su lugar. Si os fijáis, le indicamos qué paquete tiene que instalar y qué ejecutable tiene que instalar y él mismo sabe cómo hacerlo. Por ejemplo (seguramente pida permisos de admin, le metéis un sudo si lo necesitáis):

python setup.py install

También le podéis preguntar cosas al setup.py que leerá de sus metadatos para poder responderos o podéis crear tarballs etc. Para ver todas las opciones le preguntáis con –help.

Y eso es un poco todo por hoy. Tomad todo esto como una introducción porque se pueden hacer cosas mucho más complicadas y esto es sólo una ligera pincelada. Como siempre, son mis experiencias así que puede haber cosas erróneas o mejorables (si alguien las caza que me comente y me guíe). Para evitar que os quedéis sólo con esto os pongo como siempre unos links chulos que leí en su día pero se me han ido olvidando:

Y ese es el rollo. Espero que le sea útil a alguien.

Un saludo.


[1] Cuando programas copiar no es trampa. Hablaré de eso un día.

[2] Soy teleco, lo mío es Fourier y el electromagnetismo (en todas sus formas, luz incluida). Aunque, los que tenemos buen gusto, sabemos de informática un poco también 😉

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s