Ir al contenido principal

Distribución de paquetes Python

Introducción

Cuando desarrollamos una biblioteca o aplicación en Python que puede ser útil para otros programadores, el siguiente paso lógico es compartirla con la comunidad. Python cuenta con un ecosistema robusto para la distribución de paquetes que permite a los desarrolladores publicar y compartir su código de manera eficiente. En este artículo, exploraremos el proceso de preparación, empaquetado y distribución de proyectos Python, desde la estructuración adecuada del código hasta su publicación en PyPI (Python Package Index), el repositorio oficial de paquetes Python.

Aprender a distribuir tus propios paquetes no solo te permitirá contribuir a la comunidad de código abierto, sino que también te ayudará a organizar mejor tus proyectos personales y a hacerlos más accesibles para tus colaboradores.

Estructura básica de un paquete Python

Antes de distribuir nuestro código, necesitamos organizarlo adecuadamente. La estructura típica de un paquete Python es:

mi_paquete/
├── LICENSE
├── README.md
├── pyproject.toml
├── setup.py
├── src/
│   └── mi_paquete/
│       ├── __init__.py
│       ├── modulo1.py
│       └── modulo2.py
└── tests/
    ├── __init__.py
    ├── test_modulo1.py
    └── test_modulo2.py

Vamos a crear un ejemplo sencillo para ilustrar el proceso:

# src/mi_paquete/__init__.py
"""Un paquete de ejemplo para demostrar la distribución."""

__version__ = "0.1.0"
# src/mi_paquete/calculadora.py
"""Módulo con funciones básicas de calculadora."""

def sumar(a, b):
    """Suma dos números y devuelve el resultado."""
    return a + b

def restar(a, b):
    """Resta b de a y devuelve el resultado."""
    return a - b

def multiplicar(a, b):
    """Multiplica dos números y devuelve el resultado."""
    return a * b

def dividir(a, b):
    """Divide a entre b y devuelve el resultado.
    
    Lanza ZeroDivisionError si b es cero.
    """
    if b == 0:
        raise ZeroDivisionError("No se puede dividir por cero")
    return a / b

Archivos de configuración

pyproject.toml

El archivo pyproject.toml es el estándar moderno para configurar proyectos Python. Define cómo se debe construir el paquete:

[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "mi-calculadora"
version = "0.1.0"
description = "Una biblioteca de calculadora simple"
readme = "README.md"
authors = [
    {name = "Tu Nombre", email = "tu.email@ejemplo.com"}
]
license = {text = "MIT"}
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
]
requires-python = ">=3.7"

[project.urls]
"Homepage" = "https://github.com/tuusuario/mi-calculadora"
"Bug Tracker" = "https://github.com/tuusuario/mi-calculadora/issues"

setup.py

Aunque pyproject.toml es el método recomendado actualmente, muchos proyectos aún utilizan setup.py para compatibilidad:

# setup.py
from setuptools import setup, find_packages

setup(
    name="mi-calculadora",
    version="0.1.0",
    author="Tu Nombre",
    author_email="tu.email@ejemplo.com",
    description="Una biblioteca de calculadora simple",
    long_description=open("README.md").read(),
    long_description_content_type="text/markdown",
    url="https://github.com/tuusuario/mi-calculadora",
    package_dir={"": "src"},
    packages=find_packages(where="src"),
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires=">=3.7",
)

README.md

Es esencial proporcionar documentación clara:

# Mi Calculadora

Una biblioteca Python simple que proporciona funciones básicas de calculadora.

## Instalación

```bash
pip install mi-calculadora

Uso

from mi_paquete.calculadora import sumar, restar

resultado1 = sumar(5, 3)  # 8
resultado2 = restar(10, 4)  # 6

Licencia

Este proyecto está bajo la Licencia MIT.


### LICENSE

El archivo de licencia (en este caso, una licencia MIT):

MIT License

Permission is hereby granted, free of charge, to any person obtaining a copy of this software...


## Creación del paquete

Una vez que hemos estructurado nuestro proyecto, podemos crear los archivos de distribución:

```bash
python -m pip install --upgrade build
python -m build

Esto generará dos archivos en el directorio dist/:

  • Un archivo .tar.gz (distribución de código fuente)
  • Un archivo .whl (distribución wheel, formato binario)

Publicación en PyPI

Para publicar nuestro paquete en el Python Package Index (PyPI), necesitamos seguir estos pasos:

  1. Registrarse en PyPI
  2. Instalar twine:
python -m pip install --upgrade twine
  1. Subir el paquete a PyPI:
python -m twine upload dist/*

Te solicitará tu nombre de usuario y contraseña de PyPI.

TestPyPI

Antes de publicar en el PyPI oficial, es recomendable probarlo en TestPyPI:

python -m twine upload --repository testpypi dist/*

Luego puedes instalar tu paquete desde TestPyPI:

pip install --index-url https://test.pypi.org/simple/ mi-calculadora

Automatización del proceso de publicación

Para facilitar el mantenimiento y la publicación de versiones, podemos usar herramientas de integración continua como GitHub Actions:

# .github/workflows/python-publish.yml
name: Publicar paquete Python

on:
  release:
    types: [created]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Configurar Python
      uses: actions/setup-python@v2
      with:
        python-version: '3.x'
    - name: Instalar dependencias
      run: |
        python -m pip install --upgrade pip
        pip install build twine
    - name: Construir y publicar
      env:
        TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
        TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
      run: |
        python -m build
        twine upload dist/*

Versionado semántico

Es importante seguir una convención de versionado para tu paquete. El versionado semántico (SemVer) es ampliamente utilizado:

  • MAYOR.MENOR.PARCHE (ejemplo: 1.2.3)
    • Incrementa MAYOR cuando realizas cambios incompatibles
    • Incrementa MENOR cuando añades funcionalidad compatible con versiones anteriores
    • Incrementa PARCHE cuando corriges errores compatibles con versiones anteriores

Mejores prácticas para la distribución de paquetes

  1. Usa un sistema de control de versiones como Git para rastrear cambios en tu código.
  2. Incluye pruebas para verificar que tu paquete funciona como se espera.
  3. Documenta tu código con docstrings y proporciona un README completo.
  4. Especifica dependencias para asegurar que tu paquete se instale correctamente.
  5. Utiliza entornos virtuales para probar la instalación de tu paquete.
  6. Incluye clasificadores que ayuden a los usuarios a encontrar tu paquete.
  7. Usa una licencia adecuada para tu proyecto.

Comandos útiles para el desarrollo de paquetes

  • Instalar tu paquete en modo desarrollo:
pip install -e .
  • Ejecutar pruebas:
pytest
  • Verificar el estilo del código:
flake8 src/
  • Generar documentación:
sphinx-build -b html docs/source/ docs/build/html

Resumen

La distribución de paquetes Python es un proceso estructurado que permite compartir tu código con otros desarrolladores de manera eficiente. Desde la organización inicial del proyecto hasta su publicación en PyPI, cada paso es importante para asegurar que tu paquete sea accesible, usable y mantenible. A medida que desarrolles más proyectos, este conocimiento te permitirá contribuir activamente al ecosistema Python y mejorar tus habilidades de organización y documentación de código.

Al dominar la distribución de paquetes, no solo estarás compartiendo tu trabajo con la comunidad, sino que también estarás adoptando buenas prácticas que te ayudarán en cualquier proyecto de desarrollo de software, independientemente de su tamaño o complejidad.