Despliegue con Setuptools

Setuptools, es una biblioteca de extensión que se utiliza comúnmente para distribuir bibliotecas y extensiones de Python. Extiende distutils, un sistema básico de instalación de módulos incluido en Python, para soportar también varias construcciones más complejas que hacen que las aplicaciones más grandes sean más fáciles de distribuir:

  • Soporte para dependencias: Una librería o aplicación puede declarar una lista de otras librerías de las que depende, que se instalarán automáticamente por ti.

  • Registro de paquetes: setuptools registra su paquete con su instalación de Python. Esto permite consultar la información proporcionada por un paquete desde otro paquete. La característica más conocida de este sistema es el soporte de punto de entrada que permite a un paquete declarar un «punto de entrada» al que otro paquete puede engancharse para extender el otro paquete.

  • Gestor de instalación: pip puede instalar otras bibliotecas por ti.

El propio Flask y todas las bibliotecas que puedes encontrar en PyPI se distribuyen con setuptools o distutils.

En este caso asumimos que tu aplicación se llama tuaplicacion.py y que no estás usando un módulo, sino un paquete. Si aún no has convertido tu aplicación en un paquete, dirígete a Grandes aplicaciones como paquetes para ver cómo hacerlo.

Un despliegue de trabajo con setuptools es el primer paso hacia escenarios de despliegue más complejos y automatizados. Si quieres automatizar completamente el proceso, lee también el capítulo Despliegue con Fabric.

Script de configuración básica

Como tienes Flask instalado, tienes setuptools disponible en tu sistema. Flask ya depende de setuptools.

Se aplica la exención de responsabilidad estándar: use a virtualenv.

Su código de instalación siempre va en un archivo llamado setup.py junto a su aplicación. El nombre del archivo es sólo una convención, pero como todo el mundo buscará un archivo con ese nombre, es mejor que no lo cambies.

Un archivo básico setup.py para una aplicación Flask tiene el siguiente aspecto:

from setuptools import setup

setup(
    name='Your Application',
    version='1.0',
    long_description=__doc__,
    packages=['yourapplication'],
    include_package_data=True,
    zip_safe=False,
    install_requires=['Flask']
)

Tenga en cuenta que tiene que listar los subpaquetes explícitamente. Si quiere que setuptools busque los paquetes automáticamente, puede utilizar la función find_packages:

from setuptools import setup, find_packages

setup(
    ...
    packages=find_packages()
)

La mayoría de los parámetros de la función setup deberían ser autoexplicativos, include_package_data y zip_safe podrían no serlo. include_package_data le dice a setuptools que busque un archivo MANIFEST.in e instale todas las entradas que coincidan como datos del paquete. Usaremos esto para distribuir los archivos estáticos y las plantillas junto con el módulo de Python (ver Distribución de recursos). La bandera zip_safe puede utilizarse para forzar o evitar la creación de archivos zip. En general, probablemente no quieras que tus paquetes se instalen como archivos zip porque algunas herramientas no los soportan y dificultan mucho la depuración.

Etiquetado de Builds

Es útil para distinguir entre las compilaciones de lanzamiento y las de desarrollo. Añade un archivo setup.cfg para configurar estas opciones.

[egg_info]
tag_build = .dev
tag_date = 1

[aliases]
release = egg_info -Db ''

Al ejecutar python setup.py sdist se creará un paquete de desarrollo con «.dev» y la fecha actual añadida: flaskr-1.0.dev20160314.tar.gz. Ejecutando python setup.py release sdist se creará un paquete de lanzamiento con sólo la versión: flaskr-1.0.tar.gz.

Distribución de recursos

Si intenta instalar el paquete que acaba de crear, se dará cuenta de que carpetas como static o templates no se instalan por usted. La razón de esto es que setuptools no sabe qué archivos añadir por usted. Lo que debe hacer, es crear un archivo MANIFEST.in junto a su archivo setup.py. Este archivo lista todos los archivos que deben ser añadidos a su tarball:

recursive-include yourapplication/templates *
recursive-include yourapplication/static *

¡No olvide que, aunque los incluya en su archivo MANIFEST.in, no se instalarán si no establece el parámetro include_package_data de la función setup a True!

Declarar las dependencias

Las dependencias se declaran en el parámetro install_requires como una lista. Cada elemento de esa lista es el nombre de un paquete que debe ser extraído de PyPI en la instalación. Por defecto, siempre se utilizará la versión más reciente, pero también se pueden proporcionar requisitos de versión mínimos y máximos. Aquí algunos ejemplos:

install_requires=[
    'Flask>=0.2',
    'SQLAlchemy>=0.6',
    'BrokenPackage>=0.7,<=1.0'
]

Como se mencionó anteriormente, las dependencias se extraen de PyPI. ¿Qué pasa si quieres depender de un paquete que no se puede encontrar en PyPI y no se encontrará porque es un paquete interno que no quieres compartir con nadie? Simplemente hazlo como si hubiera una entrada en PyPI y proporciona una lista de ubicaciones alternativas donde setuptools debería buscar los tarballs:

dependency_links=['http://example.com/yourfiles']

Asegúrese de que esa página tiene un listado de directorios y que los enlaces de la página apuntan a los verdaderos tarballs con sus nombres de archivo correctos, ya que así es como setuptools encontrará los archivos. Si tiene un servidor interno de la empresa que contiene los paquetes, proporcione la URL de ese servidor.

Instalación / Desarrollo

Para instalar tu aplicación (idealmente en un virtualenv) simplemente ejecuta el script setup.py con el parámetro install. Instalará tu aplicación en la carpeta site-packages del virtualenv y también descargará e instalará todas las dependencias:

$ python setup.py install

Si está desarrollando en el paquete y también quiere que se instalen los requisitos, puede utilizar el comando develop en su lugar:

$ python setup.py develop

Esto tiene la ventaja de que sólo se instala un enlace a la carpeta de paquetes del sitio en lugar de copiar los datos. De este modo, puede continuar trabajando en el código sin tener que ejecutar install de nuevo después de cada cambio.