3.1Módulos, packages y biblioteca estándar
Lo esencial en 30 segundos
- Un módulo = un archivo .py, un package = una carpeta de módulos : se reutiliza vía import en lugar de copiar-pegar — from stats import frequence, alias import x as y.
- La biblioteca estándar es el cofre ya pagado : pathlib, datetime, collections, itertools, argparse, sqlite3 — probado, documentado, sin dependencia por instalar.
- El bloque __main__ separa uso importado y uso directo : la demo solo corre en ejecución directa, nunca al importar — fin de los efectos secundarios.
Mini-caso hilado — Nabil ordena sus scripts de análisis
Nabil, analista de datos junior en Alger, analiza las ventas con tres scripts que se copian las mismas funciones de limpieza : una corrección en Alger-centre, olvidada en la copia Oran, falsea un informe. Ordena lo común en un módulo stats.py (función frequence con Counter), importa vía from stats import frequence, protege la demo con if __name__ == "__main__", y sustituye su bricolaje de fechas por datetime y pathlib de la estándar. Un solo código, tres análisis correctos.
Este mismo caso vuelve en el curso, el esquema, el guion y el reto 48h.
1. Módulos, packages e imports limpios
Cuando el proyecto crece, meterlo todo en un solo archivo se vuelve ingestionable : un módulo es un archivo .py reutilizable (import stats y luego stats.frequence()), un package es una carpeta que agrupa módulos coherentes. Se importa al inicio del archivo, agrupados (estándar → terceros → locales), en absoluto (from monapp import stats), con las variantes import math, from math import sqrt, import x as y — y nunca from x import * que contamina el espacio de nombres.
El bloque if __name__ == "__main__": hace un archivo a la vez ejecutable e importable : el código bajo este bloque solo corre lanzado directamente (python stats.py), no al importar. Nabil coloca ahí su demo sobre una muestra de ventas de Alger : importado, el módulo solo ofrece funciones ; ejecutado, muestra el ejemplo. Los imports circulares (A importa B que importa A) señalan una división por revisar, no un truco por forzar.
2. La biblioteca estándar : comprobar antes de instalar
Python viene con las pilas : pathlib (rutas modernas), datetime (fechas y horas), collections (Counter, defaultdict), itertools (iteraciones), argparse (interfaces de línea de comandos), sqlite3 (base integrada), sin olvidar os, sys, json, random, math. Antes de todo pip install, Nabil revisa el cofre estándar : contar las ventas por ciudad con Counter, listar una carpeta con pathlib, fechar una exportación con datetime.
Reflejo profesional : estándar primero, PyPI después. La estándar está probada, documentada y sin dependencia — cada biblioteca externa añade un coste (instalación, versiones, mantenimiento). Nabil solo saca pip para lo que la estándar no cubre (análisis tabular, gráficos del nivel 4), y mantiene sus imports absolutos y agrupados para seguir legible.
🔎 Ejemplo concreto — Stats de ventas en módulo protegido
Nabil cuenta las ventas por ciudad desde un módulo reutilizable.
from collections import Counter
def frequence(contacts):
return Counter(c["ville"] for c in contacts)
if __name__ == "__main__":
echantillon = [{"ville": "Alger"}, {"ville": "Oran"}, {"ville": "Alger"}]
print(frequence(echantillon))
Lectura : importado = solo funciones ; ejecutado directamente = demo sobre la muestra.
Lección : el bloque __main__ protege de los efectos secundarios al importar.
Vocabulario de la sección
- Módulo
- Un archivo .py reutilizable : se accede con import mon_module, luego mon_module.fonction().
Ejemplo sencillo: El stats.py de Nabil importado por sus tres análisis.
Lo que no es: un copiar-pegar de la función en cada script.
Reflejo: ordenar lo común en un módulo desde la 2ª copia.
- Package
- Una carpeta que agrupa módulos coherentes para estructurar un proyecto.
Ejemplo sencillo: Una carpeta monapp/ con stats.py y nettoyage.py.
Lo que no es: veinte archivos .py sueltos sin carpeta.
Reflejo: agrupar por tema, importar en absoluto.
- import / from / as
- Carga código reutilizable : import math, from math import sqrt, import x as y ; nunca from x import *.
Ejemplo sencillo: El from stats import frequence de Nabil.
Lo que no es: el from stats import * que contamina el namespace.
Reflejo: importar explícito, al inicio, agrupado.
- Biblioteca estándar
- Módulos incluidos de oficio con Python : datetime, pathlib, collections, itertools, argparse, sqlite3, os, json, random, math…
Ejemplo sencillo: Counter para las ciudades, datetime para fechar la exportación de Nabil.
Lo que no es: instalar un paquete externo para lo que Counter ya hace.
Reflejo: comprobar la estándar antes de pip install.
- if __name__ == "__main__"
- Bloque ejecutado solo en lanzamiento directo, no al importar : separa la demo de las funciones.
Ejemplo sencillo: La demo sobre la muestra de Nabil, muda al importar.
Lo que no es: un print de prueba que se repite en cada import.
Reflejo: __main__ sistemático para toda demo.
En la práctica — Organizar en módulos y explotar la stdlib
- Cread un módulo « stats.py » con dos funciones (p. ej. frequence, moyenne), luego importadlo en otro archivo y llamad a sus funciones.
- Explorad la stdlib : datetime.now() para fechar una exportación, Counter para contar ciudades, pathlib para listar una carpeta.
- Usad « from module import fonction » y el alias « import x as y » : comparad la legibilidad de ambos estilos.
- Añadid un bloque « if __name__ == '__main__' » con una demo : comprobad que no se ejecuta al importar.
Guion listo para decir — presentar su módulo (30 s)
« Lo común vive en stats.py : función frequence con Counter, importada por from stats import frequence, demo protegida bajo __main__. Fechas y rutas vía datetime y pathlib de la estándar, imports absolutos al inicio, nunca estrella. Un solo código para tres análisis. »
Para decir en revisión ; mostrar el import y el bloque __main__.
Modelo copiar-pegar — módulo + import protegido
from collections import Counter
from datetime import datetime
from pathlib import Path
def frequence(contacts):
return Counter(c["ville"] for c in contacts)
def dater_export():
return datetime.now().strftime("%Y-%m-%d")
if __name__ == "__main__":
print(frequence([{"ville": "Alger"}]))
print(sorted(Path(".").iterdir()))
Independiente
Un módulo stats.py con Counter basta para fiabilizar los informes mensuales.
PYME en Alger
Nabil comparte su módulo entre los análisis Alger-centre y Oran sin recopiar.
Equipo de producto
Imponer imports absolutos agrupados y __main__ sistemático para módulos importables.
Principiante
Esta semana : un módulo, dos funciones, una demo bajo __main__.
✓ Buenas prácticas
- Colocar un bloque __main__ sistemático para toda demo o prueba manual.
- Comprobar la biblioteca estándar antes de instalar nada.
- Importar en absoluto, agrupado (estándar → terceros → locales), nunca con *.
✗ Errores frecuentes
- Copiar-pegar una función entre archivos en lugar de hacer un módulo.
- Usar from x import * (nombres sobrescritos, origen ilegible).
- Chapucear imports circulares en lugar de redividir los módulos.
Puntos clave
- MÓDULO = un archivo .py ; PACKAGE = una carpeta de módulos : se importa (from/as) en lugar de recopiar.
- La BIBLIOTECA ESTÁNDAR cubre fechas, rutas, conteos, CLI, base integrada… SIN instalar nada.
- if __name__ == '__main__' separa el código EJECUTABLE (demo) del código IMPORTABLE (funciones).
- Imports LIMPIOS : al inicio, agrupados, ABSOLUTOS, nunca estrella ; circulares = división por revisar.
Reto 48h — aplica mañana
Extraed 1 función duplicada en un módulo importado por 2 scripts, con demo bajo __main__.
- Distingo módulo (archivo) y package (carpeta).
- Mis imports son absolutos, agrupados, sin estrella.
- Mi demo bajo __main__ ya no corre al importar.
Preguntas frecuentes
¿Qué diferencia hay entre « import math » y « from math import sqrt »?
import math carga todo el módulo, a llamar con math.sqrt() (origen explícito). from math import sqrt solo importa sqrt, llamable directamente. La primera forma se lee mejor en equipo ; evitad from module import * que contamina el espacio de nombres y oculta las colisiones.
¿Para qué sirve realmente « if __name__ == '__main__' »?
Para hacer un archivo a la vez ejecutable e importable : el código bajo este bloque solo corre lanzado directamente (python fichier.py), no al importar. Ahí se pone la demo o el punto de entrada — importado, el módulo solo ofrece funciones, sin efecto secundario.
¿Qué pasa con el bloque if __name__ == "__main__" al importar?