Construya paquetes de Python: Guía del desarrollo hasta PyPI
Maestra el empaquetado de Python desde el código hasta la implementación en PyPI
Empaquetado de Python ha evolucionado significativamente, con herramientas modernas y estándares que hacen más fácil que nunca distribuir tu código.
Esta guía te lleva paso a paso por el proceso de construcción de paquetes profesionales de Python y su publicación en PyPI. Si eres nuevo en Python o necesitas una referencia rápida, consulta nuestro Hoja de trucos de Python para ponerte al día con los fundamentos de Python.

¿Por qué empaquetar tu código de Python?
Empaquetar tu proyecto de Python ofrece múltiples beneficios:
- Reutilización: Comparte código entre múltiples proyectos sin copiar y pegar
- Distribución: Permite que otros instalen tu código con un simple
pip install - Gestión de dependencias: Especifica claramente y gestiona las dependencias
- Versionado: Rastrea liberaciones y mantiene la compatibilidad hacia atrás
- Estándares profesionales: Sigue las mejores prácticas de la comunidad de Python
- Documentación: Estructura que fomenta una documentación y pruebas adecuadas
Estructura moderna de paquetes de Python
Un paquete bien organizado sigue esta estructura:
my-package/
├── src/
│ └── mypackage/
│ ├── __init__.py
│ ├── core.py
│ └── utils.py
├── tests/
│ ├── __init__.py
│ └── test_core.py
├── docs/
│ └── index.md
├── .github/
│ └── workflows/
│ └── publish.yml
├── pyproject.toml
├── README.md
├── LICENSE
└── .gitignore
La src-layout es ahora preferida sobre la estructura plana porque:
- Evita importaciones accidentales de código no instalado durante el desarrollo
- Hace más confiables las pruebas al obligar la instalación
- Separa claramente el código fuente de otros archivos del proyecto
Al organizar la estructura interna de tu paquete, considera aplicar principios de arquitectura limpia para hacer tu código más mantenible y testable. Nuestra guía sobre Patrones de diseño de Python para arquitectura limpia cubre los principios SOLID, la inyección de dependencias y patrones de arquitectura en capas que funcionan excelente con paquetes de Python.
El archivo pyproject.toml: configuración moderna
pyproject.toml (PEP 518, 621) es el estándar moderno para la configuración de proyectos de Python, reemplazando al antiguo setup.py:
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "mypackage"
version = "0.1.0"
description = "Un paquete fantástico de Python"
readme = "README.md"
requires-python = ">=3.8"
license = {text = "MIT"}
authors = [
{name = "Tu nombre", email = "tú@example.com"}
]
keywords = ["ejemplo", "tutorial", "paquete"]
classifiers = [
"Estado de desarrollo :: 4 - Beta",
"Público objetivo :: Desarrolladores",
"Licencia :: Aprobada por OSI :: Licencia MIT",
"Lenguaje de programación :: Python :: 3",
"Lenguaje de programación :: Python :: 3.8",
"Lenguaje de programación :: Python :: 3.9",
"Lenguaje de programación :: Python :: 3.10",
"Lenguaje de programación :: Python :: 3.11",
"Lenguaje de programación :: Python :: 3.12",
]
dependencies = [
"requests>=2.28.0",
"click>=8.1.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.4.0",
"black>=23.0.0",
"flake8>=6.0.0",
"mypy>=1.5.0",
]
docs = [
"sphinx>=7.0.0",
"sphinx-rtd-theme>=1.3.0",
]
[project.urls]
Homepage = "https://github.com/yourusername/mypackage"
Documentation = "https://mypackage.readthedocs.io"
Repository = "https://github.com/yourusername/mypackage"
Issues = "https://github.com/yourusername/mypackage/issues"
[project.scripts]
mypackage-cli = "mypackage.cli:main"
[tool.setuptools.packages.find]
where = ["src"]
Secciones clave de configuración
- build-system: Especifica el backend de construcción (setuptools, hatchling, poetry-core, flit-core)
- project: Metadatos y dependencias principales
- project.optional-dependencies: Dependencias adicionales para características (dev, docs, pruebas)
- project.scripts: Puntos de entrada para la línea de comandos
- tool.*: Configuración específica de herramientas (black, pytest, mypy, etc.)
Elegir un backend de construcción
Setuptools (opción estándar)
La opción más utilizada y compatible:
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"
Ventajas: Compatibilidad universal, características extensas, ecosistema grande Desventajas: Configuración más verbosa, más lento que alternativas modernas
Hatchling (moderno y rápido)
Backend moderno y liviano:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Ventajas: Construcciones rápidas, configuración simple, buenos valores predeterminados Desventajas: Menos plugins que setuptools
Poetry (todo en uno)
Gestión completa de dependencias y entornos:
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "mypackage"
version = "0.1.0"
description = "Un paquete fantástico de Python"
authors = ["Tu nombre <tú@example.com>"]
[tool.poetry.dependencies]
python = "^3.8"
requests = "^2.28.0"
Ventajas: Resolución de dependencias, archivos de bloqueo, flujo de trabajo integrado Desventajas: Flujo de trabajo diferente, superficie de herramientas más grande
Flit (minimalista)
Herramienta simple para paquetes simples:
[build-system]
requires = ["flit_core >=3.2,<4"]
build-backend = "flit_core.buildapi"
Ventajas: Muy simple, configuración mínima Desventajas: Pocas características para paquetes complejos
Construyendo tu paquete
Instalar herramientas de construcción
# Instalar la herramienta moderna de construcción
pip install build
# O para Poetry
pip install poetry
# O para Hatchling
pip install hatch
Construir archivos de distribución
Usando el paquete build (funciona con cualquier backend):
# Limpiar construcciones previas
rm -rf dist/ build/ *.egg-info
# Construir distribución de código fuente y rueda
python -m build
# Esto crea:
# dist/mypackage-0.1.0.tar.gz (distribución de código fuente)
# dist/mypackage-0.1.0-py3-none-any.whl (rueda)
Usando Poetry:
poetry build
Usando Hatch:
hatch build
Entendiendo los formatos de distribución
Distribución de código fuente (sdist) - .tar.gz
- Contiene código fuente y instrucciones de construcción
- Los usuarios de pip lo construyen durante la instalación
- Incluye pruebas, documentación y otros archivos de desarrollo
Rueda - .whl
- Distribución binaria preconstruida
- Instalación rápida (sin paso de construcción)
- Plataforma específica o puramente en Python
- Formato recomendado para la distribución
Publicar en PyPI
Método 1: Subida manual con Twine (tradicional)
# Instalar twine
pip install twine
# Verificar el paquete antes de subir
twine check dist/*
# Subir primero a TestPyPI (recomendado)
twine upload --repository testpypi dist/*
# Probar instalación desde TestPyPI
pip install --index-url https://test.pypi.org/simple/ mypackage
# Subir a PyPI de producción
twine upload dist/*
Configurar credenciales en ~/.pypirc:
[distutils]
index-servers =
pypi
testpypi
[pypi]
username = __token__
password = pypi-AgEIcHlwaS5vcmc...
[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = pypi-AgENdGVzdC5weXBpLm9yZw...
Método 2: Publicación confiable (recomendado para CI/CD)
La publicación confiable utiliza OpenID Connect (OIDC) para autenticarse desde plataformas de CI/CD sin almacenar tokens.
Configuración en PyPI:
- Ir a la configuración del proyecto en PyPI
- Navegar a la sección “Publicación”
- Añadir un nuevo “publicador pendiente”
- Configurar:
- Propietario: Tu nombre de usuario/organización de GitHub
- Repositorio: Nombre del repositorio
- Workflow:
publish.yml - Entorno:
release(opcional pero recomendado)
Flujo de trabajo de GitHub Actions (.github/workflows/publish.yml):
name: Publicar en PyPI
on:
release:
types: [published]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configurar Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Instalar dependencias de construcción
run: |
python -m pip install --upgrade pip
pip install build
- name: Construir paquete
run: python -m build
- name: Almacenar paquetes de distribución
uses: actions/upload-artifact@v3
with:
name: python-package-distributions
path: dist/
publish:
needs: build
runs-on: ubuntu-latest
environment: release
permissions:
id-token: write
steps:
- name: Descargar distribuciones
uses: actions/download-artifact@v3
with:
name: python-package-distributions
path: dist/
- name: Publicar en PyPI
uses: pypa/gh-action-pypi-publish@release/v1
Ventajas:
- No hay tokens de API que gestionar o proteger
- Autenticación automática mediante OIDC
- Mayor seguridad mediante reglas de protección de entornos
- Registro de auditoría de todas las publicaciones
Buenas prácticas
1. Gestión de versiones
Usa versionado semántico (SemVer): MAJOR.MINOR.PATCH
# Instalar herramienta de incremento de versiones
pip install bump2version
# Incrementar versión
bump2version patch # 0.1.0 -> 0.1.1
bump2version minor # 0.1.1 -> 0.2.0
bump2version major # 0.2.0 -> 1.0.0
Configurar en .bumpversion.cfg:
[bumpversion]
current_version = 0.1.0
commit = True
tag = True
[bumpversion:file:pyproject.toml]
search = version = "{current_version}"
replace = version = "{new_version}"
[bumpversion:file:src/mypackage/__init__.py]
search = __version__ = "{current_version}"
replace = __version__ = "{new_version}"
2. Incluir archivos esenciales
README.md: Descripción clara del proyecto, instalación, ejemplos de uso LICENSE: Elige una licencia adecuada (MIT, Apache 2.0, GPL, etc.) CHANGELOG.md: Documenta los cambios entre versiones .gitignore: Excluye artefactos de construcción, cachés, entornos virtuales
3. Pruebas completas
# Instalar dependencias de prueba
pip install pytest pytest-cov
# Ejecutar pruebas con cobertura
pytest --cov=mypackage tests/
# Generar informe de cobertura
pytest --cov=mypackage --cov-report=html tests/
Configurar en pyproject.toml:
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_functions = ["test_*"]
addopts = "--strict-markers --cov=mypackage"
4. Herramientas de calidad del código
# Formateo
black src/ tests/
# Linting
flake8 src/ tests/
# Comprobación de tipos
mypy src/
# Ordenamiento de importaciones
isort src/ tests/
Integrar en hooks pre-commit (.pre-commit-config.yaml):
repos:
- repo: https://github.com/psf/black
rev: 23.9.1
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 6.1.0
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.5.1
hooks:
- id: mypy
5. Documentación
Usa Sphinx para la documentación:
# Instalar Sphinx
pip install sphinx sphinx-rtd-theme
# Inicializar docs
cd docs
sphinx-quickstart
# Construir documentación
make html
O usa MkDocs para documentación basada en Markdown más simple:
pip install mkdocs mkdocs-material
mkdocs new .
mkdocs serve
6. Integración continua
Probar tus paquetes de Python en diferentes plataformas y entornos es crucial para la confiabilidad. Para obtener información sobre el rendimiento de Python en diferentes escenarios de despliegue, consulta nuestra comparación de Rendimiento de AWS Lambda: JavaScript vs Python vs Golang, que explora cómo se comporta Python en entornos sin servidor.
Flujo de trabajo completo de CI/CD (.github/workflows/ci.yml):
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Configurar Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Instalar dependencias
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Ejecutar pruebas
run: pytest --cov=mypackage --cov-report=xml
- name: Subir cobertura
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configurar Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Instalar dependencias
run: |
pip install black flake8 mypy
- name: Verificación de formato con Black
run: black --check src/ tests/
- name: Flake8
run: flake8 src/ tests/
- name: MyPy
run: mypy src/
Problemas comunes y soluciones
Problema 1: Errores de importación después de la instalación
Problema: El paquete está instalado pero fallan las importaciones
Solución: Asegúrate de tener una estructura de paquete adecuada con archivos __init__.py y configuración correcta en pyproject.toml:
[tool.setuptools.packages.find]
where = ["src"]
include = ["mypackage*"]
Problema 2: Dependencias faltantes
Problema: El paquete se instala pero falla en tiempo de ejecución debido a dependencias faltantes
Solución: Declara todas las dependencias de tiempo de ejecución en pyproject.toml:
[project]
dependencies = [
"requests>=2.28.0",
"click>=8.1.0",
]
Problema 3: Conflictos de versiones
Problema: El paquete funciona en desarrollo pero falla en producción
Solución: Usa entornos virtuales y especifica versiones mínimas:
# Crear entorno aislado
python -m venv .venv
source .venv/bin/activate # En Windows: .venv\Scripts\activate
# Instalar en modo editable para desarrollo
pip install -e ".[dev]"
Problema 4: Tamaño grande del paquete
Problema: El paquete tarda demasiado en descargarse/instalarse
Solución: Excluye archivos innecesarios usando MANIFEST.in:
include README.md
include LICENSE
include pyproject.toml
recursive-include src *.py
recursive-exclude * __pycache__
recursive-exclude * *.py[co]
recursive-exclude tests *
recursive-exclude docs *
Problema 5: Problemas específicos de plataforma
Problema: El paquete funciona en un sistema operativo pero falla en otro
Solución: Prueba en múltiples plataformas usando matrices de construcción de CI/CD (ver ejemplo de CI anterior)
Lista de verificación para publicar
Antes de publicar tu paquete en PyPI, verifica:
- Todos los tests pasan en diferentes versiones de Python
- El código está formateado y linteado
- README.md está completo con ejemplos
- Archivo LICENSE está incluido
- El número de versión está actualizado
- CHANGELOG.md está actualizado
- Las dependencias están especificadas correctamente
- El paquete se construye sin errores (
python -m build) - El paquete se prueba en TestPyPI
- La documentación está actualizada
- El repositorio de Git está etiquetado con la versión
- Se crea una publicación de GitHub (para publicación confiable)
Temas avanzados
Puntos de entrada y herramientas de línea de comandos
Crear interfaces de línea de comandos:
[project.scripts]
mypackage = "mypackage.cli:main"
Implementación en src/mypackage/cli.py:
import click
@click.command()
@click.option('--nombre', default='Mundo', help='Nombre a saludar')
def main(nombre):
"""Ejemplo de herramienta CLI simple"""
click.echo(f'Hola, {nombre}!')
if __name__ == '__main__':
main()
Para un ejemplo real de creación de paquetes de Python que interactúan con APIs externas, consulta nuestra guía sobre Integrar Ollama con Python, que demuestra la construcción de clientes de Python con integraciones tanto de API REST como de bibliotecas oficiales.
Sistemas de plugins
Habilitar descubrimiento de plugins:
[project.entry-points."mypackage.plugins"]
plugin_a = "mypackage_plugin_a:PluginA"
Extensiones C
Para código crítico de rendimiento:
[tool.setuptools.ext-modules]
name = "mypackage._speedups"
sources = ["src/mypackage/_speedups.c"]
Paquetes de espacio de nombres
Para paquetes distribuidos bajo un espacio de nombres común:
[tool.setuptools.packages.find]
where = ["src"]
include = ["company.*"]
[tool.setuptools.package-data]
"company.mypackage" = ["py.typed"]
Herramientas y recursos útiles
Herramientas de desarrollo de paquetes
- cookiecutter: Plantillas de proyectos para paquetes de Python
- tox: Automatización de pruebas en múltiples versiones de Python
- nox: Automatización de pruebas flexible (alternativa a tox)
- pre-commit: Marco de hooks de Git para la calidad del código
- commitizen: Estandarizar mensajes de commit y versionado
Plataformas de documentación
- Read the Docs: Hosting de documentación gratuito
- GitHub Pages: Anfitrión de documentación de MkDocs o Sphinx
- pdoc: Generador de documentación de API simple
Registros de paquetes
- PyPI: El índice oficial de paquetes de Python (pypi.org)
- TestPyPI: Entorno de prueba (test.pypi.org)
- Anaconda.org: Distribución de paquetes de Conda
- GitHub Packages: Hosting de paquetes privados
Monitoreo y análisis
- PyPI Stats: Estadísticas de descargas para paquetes
- Libraries.io: Monitoreo de dependencias y alertas
- Snyk: Escaneo de vulnerabilidades de seguridad
- Dependabot: Actualizaciones automatizadas de dependencias
Conclusión
El empaquetado moderno de Python ha evolucionado para ser amigable con los desarrolladores con estándares como pyproject.toml, poderosos backends de construcción y publicación segura mediante Publicación confiable. Siguiendo esta guía, puedes crear paquetes profesionales y mantenibles de Python que sirvan eficazmente a tus usuarios.
Puntos clave:
- Usa pyproject.toml para todos los nuevos proyectos
- Elige el backend de construcción adecuado para tus necesidades
- Implementa pruebas automatizadas y CI/CD
- Usa Publicación confiable para despliegues seguros sin tokens
- Sigue versionado semántico y mantén los registros de cambios
- Proporciona documentación y ejemplos completos
El ecosistema de empaquetado de Python continúa mejorando con mejoras en herramientas, estándares y características de seguridad. Mantén actualizado con las Propuestas de Mejora de Python (PEPs) y las mejores prácticas de la comunidad para mantener tus paquetes modernos y mantenibles.
Enlaces útiles
- Guía del usuario de empaquetado de Python
- PEP 518 - Especificando requisitos del sistema de construcción
- PEP 621 - Almacenar metadatos del proyecto en pyproject.toml
- Documentación de Publicación confiable de PyPI
- Documentación de Setuptools
- Documentación de Poetry
- Documentación de Hatch
- TestPyPI
- GitHub de la Autoridad de Empaquetado de Python
- Versionado semántico
- Elige una licencia