10 - Publicación de paquetes en PyPI

Objetivo del tema

En esta unidad recorrerás el ciclo completo para empaquetar código con pip, preparar la estructura según las guías de Python y publicar versiones estables en PyPI garantizando trazabilidad y mantenimiento a largo plazo.

10.1 Introducción a la creación de paquetes

Un paquete es una distribución reutilizable de tu biblioteca, aplicación o conjunto de utilidades que podés compartir con la comunidad o con tu organización. Al publicar el paquete, otros desarrolladores pueden instalarlo con pip sin necesidad de clonar el repositorio fuente.

  • El empaquetado define metadatos (nombre, versión, autor, licencias) que facilitan la instalación y la identificación en catálogos.
  • La publicación permite distribuir artefactos listos para instalar (ruedas .whl) o archivos fuente .tar.gz.
  • Una estrategia clara de versionado y documentación reduce incidencias cuando corregís errores o entregás nuevas funcionalidades.

Antes de subir un paquete, elaborá un README completo, definí los requerimientos y creá un historial de cambios que exponga qué incluís en cada versión.

10.2 Preparar el proyecto con setup.py o pyproject.toml

Las especificaciones modernas prefieren centralizar la configuración en pyproject.toml, aunque también podés mantener compatibilidad con setup.py si tu proyecto lo necesita. El tutorial oficial de empaquetado en Packaging Python describe la estructura recomendada.

Una estructura básica para una biblioteca llamada mi_paquete se vería así:

mi-paquete/
|-- mi_paquete/
|   |-- __init__.py
|   `-- core.py
|-- tests/
|   `-- test_core.py
|-- README.md
|-- LICENSE
|-- pyproject.toml
`-- setup.cfg

En pyproject.toml declarás la información principal del proyecto y el backend de construcción. A continuación, un ejemplo usando setuptools:

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

[project]
name = "mi-paquete"
version = "0.1.0"
description = "Biblioteca de utilidades para demostración"
readme = "README.md"
requires-python = ">=3.10"
authors = [{ name = "Tu Nombre", email = "tu@email.com" }]
license = { text = "MIT" }
keywords = ["demo", "tutorial", "pip"]
classifiers = [
  "Programming Language :: Python :: 3",
  "License :: OSI Approved :: MIT License",
  "Operating System :: OS Independent"
]
dependencies = [
  "requests>=2.31",
  "typer>=0.12"
]

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

Si todavía necesitás mantener un setup.py mínimo para compatibilidad con herramientas legadas, podés incluir:

from setuptools import setup

setup()

Con este enfoque, la configuración real permanece en setup.cfg o en pyproject.toml, evitando lógica repetida y haciendo el archivo mantenible.

10.3 Construir el paquete (python -m build)

Tras definir la configuración, generá los artefactos instalables usando la herramienta build, que ejecuta el backend configurado y produce la rueda y el archivo fuente.

  1. Instalá las dependencias de construcción en un entorno limpio.
pip install --upgrade build
  1. Ejecutá el proceso desde la carpeta raíz del proyecto.
python -m build

Al finalizar, revisá el directorio dist/. Deberías encontrar archivos como mi_paquete-0.1.0-py3-none-any.whl y mi-paquete-0.1.0.tar.gz. Aprovechá la salida de la consola para detectar advertencias sobre metadatos incompletos o dependencias faltantes.

Antes de publicar, instalá el paquete generado en un entorno temporal y ejecutá tus tests automatizados para confirmar que los artefactos contienen todo lo necesario.

10.4 Subirlo a PyPI con twine

La subida segura utiliza twine, que se encarga de autenticarte frente al repositorio destino. Podés trabajar contra el entorno de pruebas TestPyPI antes de lanzar la versión definitiva.

  1. Instalá la herramienta y verificá su versión.
pip install --upgrade twine
twine --version
  1. Subí los archivos generados en dist/. Para TestPyPI:
twine upload --repository testpypi dist/*

La primera vez, creá una credencial en el portal y guardála en tu gestor de contraseñas. También podés configurar un archivo ~/.pypirc con tokens de API para automatizar la autenticación. Cuando valides que la instalación funciona desde TestPyPI, ejecutá el mismo comando contra el repositorio oficial sin el flag --repository.

Tras la publicación, instalá la versión desde PyPI usando pip install mi-paquete==0.1.0 en un entorno nuevo y corroborá que la distribución llega a todos tus clientes internos.

10.5 Mantener y actualizar un paquete publicado

Publicar es solo el comienzo. Mantener la calidad implica planificar actualizaciones, comunicar cambios y garantizar compatibilidad hacia atrás cuando sea posible.

  • Adoptá una estrategia de versionado semántico (por ejemplo, Mayor.Menor.Parche) y reflejala en tu documentación.
  • Automatizá pruebas con integración continua para ejecutar tests sobre las ruedas generadas y detectar regresiones antes de subir una nueva versión.
  • Publicá un archivo CHANGELOG.md o notas de versión donde expliques mejoras, correcciones y cambios incompatibles con versiones anteriores.
  • Respondé a los reportes de issues y vulnerabilidades con rapidez, liberando parches que incluyan hashes actualizados en tus ejemplos de requirements.txt.
  • Revisa periódicamente las dependencias declaradas para eliminar librerías que ya no uses y ofrecer un paquete liviano.

Para equipos grandes, replicá la publicación en repositorios privados o mirrors y firmá tus artefactos si el proceso de seguridad lo requiere.

Resumen didáctico

Empaquetar proyectos con pip implica diseñar una configuración clara, construir artefactos reproducibles, publicarlos con credenciales seguras y sostener un plan de mantenimiento. Seguir estas prácticas asegura que tus bibliotecas lleguen a PyPI listas para ser instaladas y actualizadas con confianza.