Original article: How to Build Your Very First Python Package

Hace algunos meses, decidí lanzar Caer, un paquete de Visión Artificial disponible en Python. El proceso fue extremadamente difícil. Podrás adivinar la razón - poca (y confusa) documentación, falta de buenos tutoriales, y demás.

Así que decidí escribir este artículo con la esperanza de que ayude a otras personas que estén teniendo dificultades en hacer esto. Vamos a construir un módulo muy simple y ponerlo a disposición de todo el mundo.

Los contenidos de este módulo siguen una estructura muy básica. Hay, en total, cuatro archivos de Python, cada uno de los cuales contiene solamente un método. Vamos a mantenerlo simple por ahora.

base-modulomuysimple  --> Base
└── modulomuysimple   --> Módulo Actual
    ├── extras
    │   ├── multiplica.py
    │   ├── divide.py
    ├── suma.py
    ├── resta.py

Vas a notar que tengo una carpeta llamada modulomuysimple que a su vez, contiene dos archivos de Python suma.py y resta.py. También hay una carpeta llamada extras (que contiene a multiplica.py y divide.py). Esta carpeta será la base de nuestro módulo de Python.

Sacando los __init__s

Algo que encontrarás en cualquier paquete de Python es un archivo __init__.py. Este archivo le dirá a Python que trate los directorios como módulos (o submódulos).

Dicho de manera simple, va a contener los nombres de todos los métodos de todos los archivos de Python que estén en su directorio inmediato.

Un archivo __init__.py típico tiene el siguiente formato:

from archivo import metodo 

# 'metodo' es una función que se encuentra en un archivo llamado 'archivo.py'

Al construir paquetes en Python, se requiere añadir un archivo __init__.py dentro de cada subdirectorio del paquete. Estos subdirectorios son los submódulos de tu paquete.

Para nuestro caso, añadiremos nuestros archivos __init__.py al directorio del 'módulo real' modulomuysimple, de esta manera:

from suma import suma
from resta import resta

y haremos lo mismo para la carpeta  extras, así:

from multiplica import multiplica
from divide import divide

Una vez hecho esto, ¡prácticamente estaremos a mitad del camino!

Cómo configurar setup.py

Dentro de la carpeta base-modulomuysimple (y en el mismo directorio que nuestro módulo modulomuysimple), tendremos que añadir un archivo setup.py. Este archivo es esencial si tu intención es crear el módulo real en cuestión.

Nota: Siéntete libre de nombrar el archivo setup.py como desees. Este archivo no es de denominación específica como sí lo es nuestro archivo  __init__.py.

Algunas opciones de nombre posibles son setup_mi_super_genial_paquete_python.py y paquete_python_setup.py, pero suele ser mejor práctica quedarse con setup.py.

El archivo setup.py va a contener información acerca de tu paquete, específicamente el nombre del paquete, su versión, dependencias y un montón de cosas más.

Para nuestros propósitos, no vamos a requerir metainformación avanzada, así que el siguiente código debería ajustarse a la mayoría de paquetes que construyas:

from setuptools import setup, find_packages

VERSION = '0.0.1' 
DESCRIPTION = 'Mi primer paquete de Python'
LONG_DESCRIPTION = 'Mi primer paquete de Python con una descripción ligeramente más larga'

# Configurando
setup(
       # el nombre debe coincidir con el nombre de la carpeta 	  
       #'modulomuysimple'
        name="modulomuysimple", 
        version=VERSION,
        author="Jason Dsouza",
        author_email="<tuemail@email.com>",
        description=DESCRIPTION,
        long_description=LONG_DESCRIPTION,
        packages=find_packages(),
        install_requires=[], # añade cualquier paquete adicional que debe ser
        #instalado junto con tu paquete. Ej: 'caer'
        
        keywords=['python', 'primer paquete'],
        classifiers= [
            "Development Status :: 3 - Alpha",
            "Intended Audience :: Education",
            "Programming Language :: Python :: 2",
            "Programming Language :: Python :: 3",
            "Operating System :: MacOS :: MacOS X",
            "Operating System :: Microsoft :: Windows",
        ]
)

Una vez hecho esto, ahora todo lo que tenemos que hacer es ejecutar el siguiente comando en el mismo directorio que base-modulomuysimple:

python setup.py sdist bdist_wheel

Esto va a construir todos los paquetes necesarios que requiera Python. Los comandos sdist y bdist_wheel van a crear una distribución fuente y una rueda que luego podrás cargar a PyPi.

PyPi — ¡aquí vamos!

PyPi es el repositorio oficial de Python donde se almacenan todos los paquetes de Python. Una forma de verlo es como el Github para paquetes de Python.

Para hacer disponible tu paquete de Python para personas en todo el mundo, tendrás que tener una cuenta con PyPi.

Con eso, estamos listos para cargar nuestro paquete a PyPi. ¿Recuerdas la distribución fuente y la rueda que se crearon cuando ejecutamos  python setup.py? Pues, esos serán los archivos que cargaremos a PyPi.

Pero antes de que lo hagas, necesitas instalar twine si no lo tienes instalado aún. Es tan simple como pip install twine.

Cómo cargar tu paquete a PyPi

Asumiendo que tienes twine instalado, ve y ejecuta:

twine upload dist/*

Este comando cargará los contenidos de la carpeta dist que se generó automáticamente cuando ejecutamos python setup.py. Recibirás un prompt solicitando tu usuario y contraseña de PyPi, así que ve a ingresarlos.

Ahora, si has seguido este tutorial al pie de la letra, podrías obtener un error que diga que el repositorio ya existe.

Esto usualmente ocurre porque hay una coincidencia de nombres entre el nombre de tu paquete y un paquete que ya existe. En otras palabras, cambia el nombre de tu paquete— alguien más ya ha tomado ese nombre.

¡Y eso es todo!

Para pip instalar orgullosamente tu módulo, enciende la terminal y ejecuta:

pip install <nombre_paquete> 

# en nuestro caso, esto es
pip install modulomuysimple

Observa cómo Python instala con orden tu paquete a partir de los binarios generados anteriormente.

Abre un intérprete interactivo de Python e intenta importar tu paquete:

>> import modulomuysimple as mms

>> mms.suma(2,5)
7
>> mms.resta(5,4)
1

Para acceder a los métodos de división y multiplicación (¿recuerdas que estaban en una carpeta llamada extras?), ejecuta:

>> import modulomuysimple as mms

>> mms.extras.divide(4,2)
2
>> mms.extras.multiplica(5,3)
15

Es así de simple.

¡Felicitaciones! Acabas de crear tu primer paquete de Python. Aunque sea muy simple, tu paquete ahora se encuentra disponible para ser descargado por cualquier persona en el mundo (siempre y cuando tengan Python, por supuesto).

¿Qué sigue?

Test PyPi

El paquete que usamos en este tutorial era un módulo extremadamente simple —operaciones matemáticas básicas de adición, sustracción, multiplicación y división. No tiene sentido cargarlos directamente a PyPi especialmente porque estás intentando esto por primera vez.

Por suerte, está Test PyPi, una instancia aparte de PyPi donde puedes probar y experimentar con tu paquete (tendrás que registrar una cuenta separada en la plataforma).

El proceso que sigues para cargar a Test PyPi is prácticamente el mismo con algunos pequeños cambios.

# El siguiente comando va a cargar el paquete a Test PyPi
# Se te solicitarán tus credenciales de Test PyPi 

twine upload --repository testpypi dist/*

Para descargar proyectos de Test PyPi:

pip install --index-url "https://test.pypi.org/simple/<nombre_paquete>"

Metainformación avanzada

La metainformación que usamos en el archivo setup.py era bastante básica. Puedes añadir información adicional tales como múltiples mantenedores (si los tiene), correo electrónico del autor/a, información de licencia y una multitud de datos adicionales.

Mira otros repositorios

Puede serte de mucha utilidad ver de qué manera otros repositorios han creado sus paquetes.

Cuando estaba creando Caer, constantemente veía cómo Numpy y Sonnet configuraban sus paquetes. Recomendaría que le eches un vistazo a los repositorios de Caer, Numpy y Tensorflow si planeas crear paquetes ligeramente más avanzados.