Paquetes Python: de estructura plana a código modular
Clase 21 de 25 • Curso de Python: Entornos virtuales, PEP8 y Manejo de Errores
Resumen
Organiza tu código como un profesional: convierte una estructura plana en paquetes Python bien diseñados, con init.py, importación relativa, refactor asistido por Pylance y imports ordenados según PEP 8. El objetivo: una app escalable, con un main en el root que se ejecuta fácil y un paquete central llamado news_analyzer que concentra la lógica.
¿Cómo pasar de estructura plana a paquetes escalables?
Transformar módulos sueltos en una estructura de paquetes hace el proyecto más claro y fácil de mantener. La lógica de negocio queda en un paquete principal y los ejemplos en otro, con un main mínimo que solo orquesta imports.
- Crear el paquete examples con init.py.
- Crear el paquete news_analyzer con init.py.
- Mover módulos de la app: api_client, config, exceptions, utils.
- Mantener main.py en el root para ejecutar:
python main.py
. - Confirmar que la app no depende de los ejemplos para funcionar.
Estructura sugerida:
.
├── main.py
├── examples/
│ ├── __init__.py
│ ├── ejemplo_1.py
│ └── ejemplo_2.py
└── news_analyzer/
├── __init__.py
├── api_client.py # antes: news_api_client.py (renombrado durante el refactor)
├── config.py # contiene API key y base URL
├── exceptions.py
└── utils.py
Resultado: el main solo importa lo necesario para mostrar artículos desde la API, y el paquete news_analyzer concentra la aplicación. Así, el antiguo monolito se convierte en módulos y paquetes listos para crecer.
¿Por qué dejar main.py en el root?
- Facilita ejecutar desde la línea de comandos:
python main.py
. - Evita rutas confusas de imports al ejecutar.
- Mantiene una entrada clara a la aplicación.
¿Cómo ayuda Pylance en el refactor?
- Actualiza imports al renombrar archivos dentro del paquete.
- Reduce errores por nombres desactualizados.
- Acelera el refactor al mover muchos módulos a la vez.
¿Qué es un paquete en Python y cómo se inicializa?
Un paquete es una carpeta con un archivo especial init.py. Ese archivo se ejecuta cuando se importa el paquete: se puede usar para inicializar variables o una configuración única.
Ejemplo de init.py mínimo:
# news_analyzer/__init__.py
# Inicialización del paquete: configura lo necesario una sola vez.
Los paquetes anidados son comunes: cada nivel requiere su propio init.py. Puedes tener un padre con varios hijos y, dentro de cada hijo, más paquetes y módulos. Esto permite separar la app de los tutoriales y, en proyectos grandes, organizar dominios y funcionalidades sin mezclar responsabilidades.
Práctica recomendada: en examples, crea paquetes anidados y prueba sus imports desde un archivo Python para entrenar la mecánica.
¿Qué beneficios trae una estructura por paquetes?
- Separación clara entre app y ejemplos.
- Escalabilidad: añadir nuevas funcionalidades es más simple.
- Imports organizados y predecibles.
- Código más profesional y colaborativo.
¿Cómo organizar imports y evitar errores al refactor?
Al mover archivos, es común ver errores de “no se encuentra el módulo”. Lee el traceback, identifica desde dónde busca Python y corrige la ruta de importación.
¿Cuándo usar importación relativa con punto?
Si un módulo importa a otro del mismo paquete, usa importación relativa con un punto para indicar el paquete actual.
# news_analyzer/api_client.py
# imports locales (mismo paquete): usar importación relativa
from .config import API_KEY, BASE_URL
from .exceptions import AppError # ejemplo de clase de excepción dentro del paquete
# recomendación PEP 8: los imports locales van al final del bloque de imports
Si importas desde fuera del paquete, usa ruta absoluta con el nombre del paquete:
# main.py (en el root)
from news_analyzer.config import API_KEY, BASE_URL
from news_analyzer import api_client, exceptions
Caso real tras mover archivos: el módulo api_client buscaba config en el root y falló. Solución: cambiar a importación relativa (from .config import ...
) dentro de api_client. Aplica lo mismo a exceptions.
¿Cómo ordenar imports según PEP 8?
- Primero estándar de Python.
- Luego terceros.
- Al final los imports locales del paquete, separados por una línea en blanco.
Ejecuta de nuevo python main.py
para verificar: deberías ver el listado de noticias de la primera página de la API sin errores.
¿Ya creaste paquetes anidados dentro de examples y probaste sus imports con rutas relativas y absolutas? Comparte en comentarios tu estructura y qué dudas te surgieron al hacer el refactor.