Saltar al contenido

lección 5

Módulos e imports

Organizar tu código en archivos separados, importar funcionalidad y entender la biblioteca estándar de Python.

50 min

Cuando tu script pasa de 50 líneas, mantener todo en un solo archivo se convierte en un caos. Es como tener un almacén donde todo está en un solo montón — encuentras las cosas, pero cada vez te cuesta más. Los módulos son la solución: divides tu código en archivos con responsabilidades claras, y cada archivo importa lo que necesita de los demás.

En ingeniería de datos, un proyecto típico tiene esta estructura: un módulo para leer datos (extractors), otro para transformarlos (transformers), otro para escribirlos (loaders), y un script principal que orquesta todo. Eso es el famoso patrón ETL (Extract-Transform-Load), y los módulos son lo que lo hace mantenible.

### ¿Qué es un módulo?

Un módulo en Python es simplemente un archivo .py. Eso es todo. Cuando creas "utils.py", acabas de crear un módulo llamado "utils". Cuando escribes "import utils", Python busca ese archivo y te da acceso a todo lo que hay dentro: funciones, variables, clases.

1# --- archivo: calculos.py ---
2"""Módulo con funciones de cálculo para datos de ventas."""
3
4def calcular_total(cantidad, precio_unitario):
5 """Calcula el total de una línea de venta."""
6 return cantidad * precio_unitario
7
8def aplicar_iva(importe, tasa=0.21):
9 """Aplica IVA a un importe."""
10 return importe * (1 + tasa)
11
12def calcular_descuento(importe, porcentaje):
13 """Aplica un descuento porcentual."""
14 return importe * (1 - porcentaje / 100)

calculos.py es un módulo — un archivo con funciones reutilizables.

1# --- archivo: main.py ---
2"""Script principal que usa el módulo de cálculos."""
3
4import calculos
5
6# Usar funciones del módulo
7total = calculos.calcular_total(3, 299.99)
8con_iva = calculos.aplicar_iva(total)
9final = calculos.calcular_descuento(con_iva, 10)
10
11print(f"Subtotal: {total:.2f}€")
12print(f"Con IVA: {con_iva:.2f}€")
13print(f"Con descuento 10%: {final:.2f}€")

main.py importa y usa las funciones de calculos.py.

### Formas de importar

Python te da varias formas de importar. Cada una tiene su caso de uso:

1# 1. Importar el módulo completo (recomendado para claridad)
2import calculos
3resultado = calculos.aplicar_iva(100) # Queda claro de dónde viene
4
5# 2. Importar funciones específicas (cuando usas mucho una función)
6from calculos import aplicar_iva, calcular_total
7resultado = aplicar_iva(100) # Más corto, pero menos explícito
8
9# 3. Importar con alias (para nombres largos)
10import calculos as calc
11resultado = calc.aplicar_iva(100)
12
13# 4. NUNCA hagas esto (importa TODO sin prefijo — contamina tu namespace)
14# from calculos import * ← MALO: no sabes de dónde vienen las funciones

Usa import modulo para claridad. Usa from modulo import X cuando es muy frecuente.

Evita "from modulo import *" siempre. Hace imposible saber de dónde viene cada función cuando lees el código. En un proyecto con 10 módulos, es un desastre. Sé explícito — tu yo del futuro te lo agradecerá.

### La biblioteca estándar: baterías incluidas

Python viene con cientos de módulos integrados que no necesitas instalar. Se llaman "la biblioteca estándar" y son tu primera línea de defensa antes de buscar librerías externas. Para datos, los más importantes son:

  • csv — Leer y escribir archivos CSV (ya lo conoces)
  • json — Serializar y deserializar JSON (ya lo conoces)
  • os — Interactuar con el sistema operativo (variables de entorno, rutas)
  • pathlib — Manejo moderno de rutas de archivos
  • datetime — Fechas y horas (fundamental en datos temporales)
  • collections — Estructuras avanzadas: Counter, defaultdict, OrderedDict
  • math — Funciones matemáticas: ceil, floor, sqrt
  • sys — Acceso al intérprete de Python (argumentos, rutas de búsqueda)
1from datetime import datetime, timedelta
2from collections import Counter, defaultdict
3
4# datetime — fundamental para datos temporales
5ahora = datetime.now()
6ayer = ahora - timedelta(days=1)
7print(f"Hoy: {ahora.strftime('%Y-%m-%d %H:%M')}")
8print(f"Ayer: {ayer.strftime('%Y-%m-%d')}")
9
10# Counter — contar ocurrencias (perfecto para análisis)
11categorias = ["electrónica", "ropa", "electrónica", "comida", "ropa", "ropa"]
12conteo = Counter(categorias)
13print(f"Conteo: {conteo}") # Counter({'ropa': 3, 'electrónica': 2, ...})
14print(f"Más común: {conteo.most_common(1)}") # [('ropa', 3)]
15
16# defaultdict — diccionario con valor por defecto
17ventas_por_dia = defaultdict(list)
18ventas_por_dia["lunes"].append(100)
19ventas_por_dia["lunes"].append(200)
20ventas_por_dia["martes"].append(150)
21print(dict(ventas_por_dia))

datetime y collections son tus mejores aliados para procesar datos.

Y la operación contraria: convertir un texto en fecha. Si tu CSV tiene fechas como "2024-01-15", strptime es lo que las hace operables — puedes restarlas, compararlas y saber cuántos días las separan:

1from datetime import datetime
2
3# strptime: de texto a fecha (la "p" es de "parse")
4fecha = datetime.strptime("2024-01-15", "%Y-%m-%d")
5print(fecha) # 2024-01-15 00:00:00
6
7# Restar dos fechas da una duración; .days son los días enteros
8hoy = datetime(2024, 6, 1)
9diferencia = hoy - fecha
10print(f"Han pasado {diferencia.days} días") # Han pasado 138 días

strptime convierte texto en fecha. Restar dos fechas da .days: los días que las separan.

Antes de buscar en pip una librería externa, busca si la biblioteca estándar ya lo resuelve. Python viene con "baterías incluidas" — csv, json, datetime, collections, pathlib resuelven el 80% de lo que necesitas sin instalar nada.

### Estructura de un proyecto de datos

Cuando tu proyecto crece, organizar los módulos en carpetas (paquetes) es clave. Un paquete en Python es simplemente una carpeta con un archivo __init__.py dentro (puede estar vacío). Aquí va una estructura típica de proyecto de datos:

1mi-pipeline/
2├── data/
3│ ├── raw/ # Datos originales (entrada)
4│ └── processed/ # Datos procesados (salida)
5├── src/
6│ ├── __init__.py # Marca src como paquete
7│ ├── extractors.py # Funciones para leer datos
8│ ├── transformers.py # Funciones para transformar
9│ └── loaders.py # Funciones para escribir resultados
10├── main.py # Script principal (orquesta todo)
11├── config.json # Configuración del pipeline
12├── requirements.txt # Dependencias (pip install -r)
13└── .gitignore # Archivos que no se suben a git

Estructura profesional de un proyecto de datos. Cada archivo tiene un rol claro.

El script principal importa y orquesta. Cada módulo tiene una responsabilidad.

Si no puedes explicar tu pipeline dibujándolo en una servilleta — con flechas de "esto lee de aquí" y "esto escribe allá" — es demasiado complejo. Simplifica antes de añadir más código.

## ejercicios

[01]

Crear un módulo de utilidades

Escribe tres funciones de utilidad: limpiar_texto (quitar espacios), validar_email (@ y punto después) y formatear_precio (2 decimales + €).

💡 Resultado esperado

Hola mundo
True
False
False
Cargando editor...
[02]

Trabajar con fechas de datos

Convierte fechas de texto a objetos datetime, calcula los días que han pasado desde cada una hasta una fecha de referencia, y encuentra la más reciente.

💡 Resultado esperado

2024-01-15 -> hace 138 días
2024-03-22 -> hace 71 días
2024-02-08 -> hace 114 días
2024-04-01 -> hace 61 días
Cargando editor...
[03]

Análisis de frecuencias con Counter

Usa Counter para encontrar las 3 acciones más frecuentes de un log de usuarios y el porcentaje de cada una.

💡 Resultado esperado

Top 3 acciones:
  ver_producto: 6 veces (35.3%)
  login: 5 veces (29.4%)
  añadir_carrito: 3 veces (17.6%)
Cargando editor...

Regístrate para guardar tu progreso.

## comentarios

Reporta erratas, ayuda a otros o comparte tu opinión. Sé constructivo.

Inicia sesión para comentar y responder.

cargando comentarios...