PythonAprende PythonDocumentación

Packaging y proyectos

Estructura profesional, pyproject.toml y distribución.

Un script suelto es un script; un paquete es código que otros (y tu futuro yo) pueden instalar, importar y versionar. Aquí está la estructura profesional moderna.

La estructura estándar

mi_proyecto/
├── pyproject.toml          ← metadatos y dependencias
├── README.md
├── src/
│   └── utilidades/
│       ├── __init__.py     ← marca el paquete (y exporta su API)
│       ├── textos.py
│       └── fechas.py
└── tests/
    └── test_textos.py

El src-layout tiene una virtud poco apreciada: obliga a instalar tu paquete para importarlo. Tus tests prueban el paquete instalado real, no la carpeta local — evitas tests que pasan de mentira.

pyproject.toml: el manifiesto

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "utilidades"
version = "0.1.0"
description = "Funciones de utilidad para texto y fechas"
requires-python = ">=3.10"
dependencies = [
    "requests>=2.31",
]

[project.optional-dependencies]
dev = [
    "pytest>=8.0",
    "mypy>=1.8",
]
  • [project]: nombre, versión, Python mínimo, dependencias de runtime
  • [project.optional-dependencies]: extras como devpip install -e ".[dev]" las trae todas
  • Es el estándar (PEP 517/518): los instaladores modernos lo leen todos

Instalar tu propio paquete

pip install -e ".[dev]"     # editable + dependencias de desarrollo

-e (editable) enlaza el paquete con tu código fuente: cambias un archivo y el cambio se ve al instante, sin reinstalar.

Versionado semántico

1.4.2
│ │ └── parche: arreglo de bugs, sin romper nada
│ └── menor: nueva funcionalidad compatible
└── mayor: cambios que ROMPEN compatibilidad

Sube el número correcto en cada release. Tus usuarios (incluido tú) lo agradecerán.

Compartir: PyPI

pip install build twine
python -m build              # genera el .whl y el .tar.gz en dist/
twine upload dist/*          # publica en pypi.org (requiere cuenta)

Después de publicar, cualquiera instala con pip install utilidades. Para código interno de la empresa, servidores privados o repositorios Git directamente (pip install git+https://...).

requirements.txt: todavía útil

# congelar el entorno exacto para reproducibilidad
pip freeze > requirements.txt
pip install -r requirements.txt

Para librerías tu fuente de verdad es pyproject.toml; para aplicaciones desplegadas (donde quieres versiones exactas), el congelado es la práctica de despliegue.

Herramientas que complementan

  • uv / poetry: gestores de entornos + dependencias + build en una herramienta
  • ruff: linter ultrarrápido (estilo + errores)
  • mypy: verificación estática de tus type hints

Resumen

  • src-layout + pyproject.toml es el estándar actual
  • pip install -e ".[dev]" para desarrollar con instante de feedback
  • Versionado semántico: mayor.menor.parche
  • python -m build + twine upload para publicar en PyPI
  • Los tests deben probar el paquete instalado, no la carpeta

Quiz

  1. 1. ¿Qué archivo define los metadatos y dependencias de un paquete Python moderno?

  2. 2. ¿Para qué sirve pip install -e . (editable install)?

  3. 3. ¿Qué hace el src-layout (src/mi_paquete/) por ti?

Ejercicios

Ejercicio 1: Estructura de paquete

Crea la estructura mínima de un paquete llamado utilidades: un módulo textos.py con la función normalizar(texto) (strip + lower) e imprime su resultado.

Cargando editor…

Ejercicio 2: Versionado semántico

Completa la clase Version para comparar versiones semánticas: mayor, menor y parche. `Version(1, 4, 0) > Version(1, 3, 9)` debe ser True.

Cargando editor…