Guía Formal sobre Estructuras de Proyectos en Python
El desarrollo de proyectos en Python requiere una estructura bien definida que permita mantener el código organizado, escalable y fácil de mantener. Una estructura coherente facilita la colaboración entre desarrolladores, la integración continua y la distribución del software.
Este documento describe las estructuras más comunes de proyectos Python, analizando buenas prácticas, ejemplos y herramientas modernas para la gestión de entornos, con especial énfasis en ``uv``, una herramienta de alto rendimiento para la gestión de entornos y dependencias. Además, se incluyen recomendaciones sobre el uso de Jupyter Notebooks y la organización de datos en proyectos científicos o analíticos.
1. Introducción a las estructuras de proyectos
Una estructura de proyecto en Python define cómo se organizan los archivos y directorios del código fuente, las dependencias, los scripts de configuración y los recursos auxiliares.
Los objetivos principales son:
Separar el código fuente de los datos, las notebooks y la configuración.
Facilitar la reutilización del código y la automatización de tareas.
Permitir la distribución del proyecto como paquete instalable.
Favorecer la gestión de entornos virtuales reproducibles y seguros.
Integrar de forma ordenada los notebooks de experimentación.
2. Estructura básica de un proyecto Python
Una estructura simple, adecuada para proyectos pequeños o scripts personales, puede ser la siguiente:
mi_proyecto/
│
├── venv/ # Entorno virtual (opcional)
├── main.py # Punto de entrada principal
├── requirements.txt # Dependencias del proyecto
└── README.md # Documentación básica
Esta estructura es suficiente para scripts o utilidades simples, pero no es adecuada para proyectos colaborativos o de larga duración.
3. Estructura modular (proyectos medianos y grandes)
A medida que el proyecto crece, se recomienda una organización modular y clara:
mi_proyecto/
│
├── src/ # Código fuente principal
│ └── mi_proyecto/
│ ├── __init__.py
│ ├── core.py
│ ├── utils/
│ │ └── __init__.py
│ └── data_processing.py
│
├── data/ # Carpeta para almacenar datos
│ ├── raw/ # Datos sin procesar
│ ├── processed/ # Datos limpios y transformados
│ └── external/ # Datos externos o descargados
│
├── notebooks/ # Notebooks de análisis o experimentación
│ ├── 01_exploracion.ipynb
│ ├── 02_modelado.ipynb
│ └── utils.ipynb
│
├── requirements.txt # Dependencias del proyecto
├── pyproject.toml # Configuración avanzada (PEP 621)
├── .gitignore
└── README.md
Ventajas de esta estructura
Claridad modular: separación del código fuente, notebooks y datos.
Escalabilidad: permite mantener un flujo limpio entre desarrollo y análisis.
Colaboración eficiente: notebooks separados del código productivo.
4. Estructura de proyectos con Jupyter Notebooks
Los Jupyter Notebooks (.ipynb) son herramientas esenciales para exploración de datos, visualización y prototipado rápido. Sin embargo, deben mantenerse separados del código de producción para evitar confusión y mejorar la mantenibilidad.
Estructura recomendada con notebooks
mi_proyecto/
│
├── src/ # Código fuente principal
│ └── mi_proyecto/
│ ├── __init__.py
│ ├── core.py
│ ├── model/
│ │ ├── train.py
│ │ └── evaluate.py
│ └── utils/
│ └── data_utils.py
│
├── notebooks/ # Notebooks de exploración y presentación
│ ├── 00_exploracion_inicial.ipynb
│ ├── 01_limpieza_datos.ipynb
│ ├── 02_modelado.ipynb
│ └── 03_visualizacion_resultados.ipynb
│
├── data/
│ ├── raw/
│ ├── processed/
│ ├── results/
│ └── external/
│
├── reports/ # Resultados y documentación generada
│ ├── figuras/
│ └── informe_final.pdf
│
├── environment.yml # (opcional) Configuración alternativa para Conda
├── pyproject.toml
├── requirements.txt
├── .gitignore
└── README.md
Buenas prácticas con Jupyter Notebooks
Nombrar los notebooks con prefijos numéricos para reflejar el orden lógico del flujo de trabajo. Ejemplo:
01_preprocesamiento.ipynb,02_modelado.ipynb.Evitar lógica de negocio compleja dentro de los notebooks. El código debe modularizarse y residir en
src/.Importar funciones y módulos desde ``src/`` para mantener consistencia:
from mi_proyecto.utils.data_utils import cargar_datos
Mantener notebooks limpios y ejecutables desde cero. Deben poder ejecutarse completamente tras un
Restart & Run All.Guardar los resultados procesados en
data/processed/odata/results/, no en el notebook.Exportar los notebooks a formatos reproducibles (
.htmlo.pdf) para documentación final.
5. El archivo requirements.txt
El archivo requirements.txt lista todas las dependencias necesarias para ejecutar el proyecto. Es un componente esencial para garantizar que el entorno de desarrollo y producción sean idénticos.
5.1 Ejemplo básico
numpy==2.0.1
pandas>=2.2.0,<3.0.0
matplotlib==3.9.1
scikit-learn>=1.4.0
jupyterlab==4.2.0
5.2 Creación automática
Puedes generar el archivo a partir del entorno activo:
uv pip freeze > requirements.txt
o, si usas pip tradicional:
pip freeze > requirements.txt
5.3 Instalación de dependencias
Para reproducir un entorno:
uv pip install -r requirements.txt
5.4 Buenas prácticas con requirements.txt
Especificar versiones exactas (
==) para despliegues productivos.Usar rangos (
>=, <) durante la fase de desarrollo.Complementar con
pyproject.tomlpara definir dependencias de desarrollo y metadatos.Mantener actualizado mediante
uv pip freezeo herramientas comopip-tools.
6. Gestión de entornos con uv (recomendado)
`uv <https://github.com/astral-sh/uv>`__ es una herramienta moderna desarrollada por Astral, los creadores de ruff y rye. Proporciona una gestión de entornos virtuales y dependencias ultrarrápida, reproducible y compatible con los estándares de Python.
6.1 Instalación
pip install uv
o mediante script oficial:
curl -LsSf https://astral.sh/uv/install.sh | sh
6.2 Creación y activación de entornos
uv venv
source .venv/bin/activate
Por defecto, el entorno se crea en .venv/. Es totalmente compatible con herramientas como jupyter, black y ruff.
6.3 Instalación de dependencias
uv pip install -r requirements.txt
o directamente:
uv pip install .
6.4 Ventajas de uv
Característica |
Descripción |
|---|---|
Velocidad |
Hasta 20 veces más rápido que |
Compatibilidad |
Totalmente interoperable con |
Reproducibilidad |
Crea entornos deterministas y caché inteligente. |
Ligereza |
Sin dependencias externas, multiplataforma. |
Integración |
Soporte directo para |
7. Propuesta para almacenar datos
En proyectos de análisis o ciencia de datos, los datasets deben organizarse con una estructura clara y reproducible.
data/
├── raw/ # Datos originales sin modificar
├── processed/ # Datos limpios y listos para análisis
├── external/ # Datos descargados de fuentes externas
└── results/ # Resultados o predicciones generadas
Buenas prácticas
Evitar almacenar datos grandes en el repositorio. Usa
.gitignorepara excluir/data/rawy/data/processed.Documentar el origen y formato de los datos en
data/README.md.Usar rutas relativas en el código.
Mantener una convención de nombres consistente entre datasets.
Guardar resultados reproducibles (como modelos o métricas) en
data/results/.
8. Buenas prácticas generales
Usar ``pyproject.toml`` como fuente principal de configuración.
Gestionar dependencias con ``uv`` para lograr entornos reproducibles y rápidos.
Mantener notebooks separados en
/notebooks/y código reutilizable en/src/.Guardar datos estructurados en ``/data/`` y documentar su procedencia.
Evitar almacenar entornos (``.venv/``) o datos pesados en Git.
Exportar notebooks a formatos estáticos para documentación (
.html,.pdf).Nombrar notebooks secuencialmente para reflejar el flujo de trabajo.
9. Archivo pyproject.toml
El archivo ``pyproject.toml`` es el estándar moderno para la configuración de proyectos Python definido por PEP 518 y extendido por PEP 621. Su objetivo es centralizar la información del proyecto, las dependencias, los requisitos de construcción y la configuración de herramientas en un solo archivo, reemplazando en gran medida a setup.py y requirements.txt.
9.1 Estructura básica
Un archivo pyproject.toml mínimo suele incluir las siguientes secciones:
[project]
name = "mi_proyecto"
version = "0.1.0"
description = "Descripción breve del proyecto"
authors = [{ name = "Tu Nombre", email = "tu@email.com" }]
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"numpy>=2.0.0,<3.0.0",
"pandas>=2.2.0,<3.0.0",
]
[build-system]
requires = ["setuptools>=60.0", "wheel"]
build-backend = "setuptools.build_meta"
Explicación de secciones:
[project]: contiene los metadatos del proyecto (nombre, versión, autores, descripción, dependencias).dependencies: lista de dependencias que deben instalarse para usar el proyecto.[build-system]: define las herramientas necesarias para construir e instalar el proyecto, por ejemplosetuptoolsywheel.build-backend: indica el backend de construcción que se utilizará, normalmentesetuptools.build_meta.
10. Conclusión
Una estructura de proyecto bien diseñada es la base para la reproducibilidad, colaboración y mantenimiento en el desarrollo con Python.
Entre las herramientas modernas, ``uv`` destaca por su velocidad, simplicidad y compatibilidad con los estándares más recientes. En combinación con un manejo ordenado de notebooks, dependencias y datos, proporciona un flujo de trabajo profesional, sostenible y escalable.
En resumen:
Usa ``uv`` para gestionar entornos y dependencias.
Organiza el código en
/src/y los datos en/data/.Mantén los notebooks en
/notebooks/, limpios y bien documentados.Versiona solo lo esencial: código, metadatos y resultados relevantes.
[ ]: