3.1 · Módulos, packages y biblioteca estándar

Nivel 3 · Python intermedio

3.1Módulos, packages y biblioteca estándar

Objetivo: organizar el código en módulos y packages reutilizables (import, from/as, __main__) y explotar la biblioteca estándar (datetime, pathlib, collections…) — el paso del script improvisado al proyecto estructurado.
Tiempo estimado: 14 min · lectura autónoma · Si solo tienes 5 min: lee «Lo esencial en 30s» + el esquema.

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.

Error frecuente de interpretación: « Un módulo es solo un archivo, y from x import * va más rápido ». No. El módulo solo sirve si se importa limpiamente : el import estrella sobrescribe nombres en silencio y vuelve ilegible el origen, y sin bloque __main__ cada import repite la demo. Ordenar, importar en absoluto, proteger la demo : ese trío es lo que vuelve el código reutilizable.
Código ordenado y reutilizable Módulos importables, estándar primero, imports absolutos Módulo (.py)Un archivo, funciones importables+Estándar (cofre)pathlib, datetime, collections…+Imports (absolutos)Al inicio, agrupados, nunca * Antes de pip install : comprobar la biblioteca estándar.
Módulos importables, estándar primero, imports absolutos
Versión en texto del esquema (SEO / lectores de pantalla / traducción): 1) Módulo : Nabil ordena su función frequence en stats.py y la importa (from stats import frequence) en lugar de recopiarla. 2) Estándar : el conteo por ciudad pasa por Counter, las fechas por datetime — nada que instalar. 3) Imports : al inicio, absolutos y agrupados, sin estrella ; la demo vive bajo __main__. Lección : ordenar para reutilizar, estándar primero, proteger la demo.

🔎 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

  1. Cread un módulo « stats.py » con dos funciones (p. ej. frequence, moyenne), luego importadlo en otro archivo y llamad a sus funciones.
  2. Explorad la stdlib : datetime.now() para fechar una exportación, Counter para contar ciudades, pathlib para listar una carpeta.
  3. Usad « from module import fonction » y el alias « import x as y » : comparad la legibilidad de ambos estilos.
  4. Añadid un bloque « if __name__ == '__main__' » con una demo : comprobad que no se ejecuta al importar.
Dividís vuestro código en módulos importables y explotáis la biblioteca estándar : vuestro proyecto gana en claridad y reutilización.

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__.

Lista de salida de la sección
  • Distingo módulo (archivo) y package (carpeta).
  • Mis imports son absolutos, agrupados, sin estrella.
  • Mi demo bajo __main__ ya no corre al importar.
Autoevaluación 1-5 : ¿existe una función aún en dos copias?¿ha desaparecido cada import estrella?

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.

Comprueba tu comprensión

¿Qué pasa con el bloque if __name__ == "__main__" al importar?

Recursos adicionales (opcional, para ir más allá)

Examen del nivel 3Preguntas inéditas y más difíciles para validar tus conocimientos