Módulos e importaciones en Python
En esta lección
Cuando un programa crece, meterlo todo en un único archivo se vuelve inmanejable. Python te permite repartir el código en módulos (archivos .py) y paquetes (carpetas de módulos), e importar en cada sitio solo lo que necesitas. Además, Python trae de serie una enorme biblioteca estándar con módulos para matemáticas, fechas, ficheros, JSON y mucho más. En esta lección aprenderás a importar, a crear tus propios módulos y a sacar partido de los módulos más útiles.
Qué es un módulo
Un módulo es simplemente un archivo .py. Su nombre es el del archivo sin la extensión: calculos.py es el módulo calculos. Todo lo que definas en él (variables, funciones, clases) se puede usar desde otros archivos.
¿Por qué dividir el código?
- Organización: cada archivo se ocupa de una cosa (cálculos, acceso a datos, interfaz).
- Reutilización: escribes una función una vez y la importas donde haga falta.
- Espacios de nombres:
calculos.totalypedidos.totalpueden convivir sin chocar.
Formas de importar
import modulo
Importa el módulo entero. Para usar lo que contiene, escribes el nombre del módulo, un punto y el elemento:
import math
print(math.sqrt(16)) # 4.0
print(math.pi) # 3.141592653589793
Es la forma más clara: al leer math.sqrt sabes exactamente de dónde viene sqrt.
from modulo import nombre
Trae solo algunos elementos, que luego usas sin prefijo:
from math import sqrt, pi
print(sqrt(81)) # 9.0
print(pi) # 3.141592653589793
Es cómodo si usas mucho una función concreta, pero pierdes la pista de su origen en archivos largos.
as: poner un alias
as da otro nombre a un módulo o a un elemento. Se usa para acortar nombres largos o evitar choques:
import statistics as st
from math import sqrt as raiz
print(st.mean([6, 8, 10])) # 8
print(raiz(25)) # 5.0
Algunos alias son convenciones universales que verás en todas partes, como import numpy as np o import pandas as pd.
from modulo import * (evítalo)
Importa todos los nombres públicos del módulo de golpe. Parece práctico, pero no sabes qué nombres has traído y alguno puede sobrescribir una variable tuya sin que te des cuenta. En código serio no se usa.
Crear tu propio módulo
Crea un archivo calculos.py:
"""Funciones de cálculo para la tienda."""
IVA = 0.21
def precio_con_iva(precio):
return round(precio * (1 + IVA), 2)
def aplicar_descuento(precio, porcentaje):
return round(precio * (1 - porcentaje / 100), 2)
Y en la misma carpeta, un archivo main.py que lo use:
import calculos
from calculos import aplicar_descuento
print(calculos.precio_con_iva(20)) # 24.2
print(calculos.IVA) # 0.21
print(aplicar_descuento(80, 25)) # 60.0
Ejecutas python main.py y listo. Python busca calculos.py en la carpeta del programa que estás ejecutando.
Cuidado: no llames a tus archivos igual que un módulo de Python (
random.py,math.py,json.py…). Tu archivo “taparía” al original yimport randomcargaría el tuyo, con errores muy desconcertantes comoAttributeError: module 'random' has no attribute 'randint'.
Cuando importas un módulo, Python ejecuta todo su código una vez. Las importaciones posteriores del mismo módulo reutilizan el que ya está cargado.
if __name__ == "__main__"
Como importar ejecuta el archivo, si calculos.py tuviera print de prueba sueltos, aparecerían al importarlo desde main.py. Para evitarlo existe este patrón:
# al final de calculos.py
if __name__ == "__main__":
print("Probando calculos.py...")
print(precio_con_iva(100)) # 121.0
print(aplicar_descuento(50, 10)) # 45.0
Cada módulo tiene una variable especial __name__:
| Cómo se usa el archivo | Valor de __name__ |
|---|---|
Lo ejecutas directamente: python calculos.py | "__main__" |
Otro archivo lo importa: import calculos | "calculos" |
Así, el bloque del if solo se ejecuta cuando lanzas el archivo directamente. Es ideal para pruebas rápidas o para que un archivo sirva a la vez como módulo y como programa. Muchos programas terminan con:
def main():
...
if __name__ == "__main__":
main()
Paquetes
Un paquete es una carpeta que agrupa módulos relacionados. Se marca con un archivo __init__.py (que puede estar vacío):
mi_proyecto/
├── app.py
└── tienda/
├── __init__.py
├── productos.py
└── pedidos.py
# tienda/productos.py
def crear_producto(nombre, precio):
return {"nombre": nombre, "precio": precio}
Desde app.py se importa usando puntos para indicar la ruta:
from tienda.productos import crear_producto
from tienda import pedidos
import tienda.productos
print(crear_producto("libro", 12)) # {'nombre': 'libro', 'precio': 12}
Dentro del propio paquete, un módulo puede importar a otro con un import relativo, usando un punto para “este paquete”:
# tienda/pedidos.py
from .productos import crear_producto
__init__.py se ejecuta al importar el paquete. Puedes dejarlo vacío o usarlo para exponer lo más importante: si pones from .productos import crear_producto, podrás escribir directamente from tienda import crear_producto.
Consejo: desde Python 3.3 una carpeta sin
__init__.pytambién se puede importar (se llama namespace package), pero para tus proyectos incluye siempre__init__.py: deja claro que es un paquete y evita sorpresas.
La biblioteca estándar
Python viene “con las pilas incluidas”: cientos de módulos listos para usar sin instalar nada. Estos son los que más usarás.
math: matemáticas
import math
print(math.sqrt(16), math.ceil(4.1), math.floor(4.9)) # 4.0 5 4
print(math.hypot(3, 4)) # 5.0 (hipotenusa)
random: números aleatorios
import random
dado = random.randint(1, 6) # entero entre 1 y 6, ambos incluidos
jugada = random.choice(["piedra", "papel", "tijera"]) # un elemento al azar
cartas = [1, 2, 3, 4, 5]
random.shuffle(cartas) # desordena la lista
primitiva = random.sample(range(1, 50), 6) # 6 números sin repetir
La salida cambia en cada ejecución, que es justo lo que se busca.
os: el sistema operativo
import os
print(os.getcwd()) # carpeta de trabajo actual
print(os.path.join("datos", "ventas.csv")) # datos/ventas.csv (datos\ventas.csv en Windows)
print(os.environ.get("API_KEY", "sin clave")) # variable de entorno
sys: el intérprete
import sys
print(sys.version) # versión de Python
print(sys.argv) # argumentos de la línea de comandos
Si ejecutas python std.py a b, sys.argv vale ['std.py', 'a', 'b'].
pathlib: rutas modernas
from pathlib import Path
ruta = Path("datos") / "ventas.csv"
print(ruta.name, ruta.suffix, ruta.stem) # ventas.csv .csv ventas
Lo verás a fondo en ficheros. Hoy se prefiere a os.path.
datetime: fechas
from datetime import date
print(date(2025, 12, 25) - date(2025, 12, 1)) # 24 days, 0:00:00
Tiene su propia lección: fechas con datetime.
json y csv: formatos de datos
import json
texto = json.dumps({"nombre": "Ana", "notas": [8, 9]})
print(texto) # {"nombre": "Ana", "notas": [8, 9]}
print(json.loads('{"activo": true, "edad": null}')) # {'activo': True, 'edad': None}
import csv
with open("productos.csv", encoding="utf-8") as f:
for fila in csv.DictReader(f):
print(fila) # {'nombre': 'pan', 'precio': '1.2'} ...
Los dos se explican en detalle en ficheros y JSON.
collections: estructuras extra
from collections import Counter, defaultdict
votos = ["rojo", "azul", "rojo", "verde", "rojo", "azul"]
conteo = Counter(votos)
print(conteo) # Counter({'rojo': 3, 'azul': 2, 'verde': 1})
print(conteo.most_common(1)) # [('rojo', 3)]
por_ciudad = defaultdict(list)
for nombre, ciudad in [("Ana", "Madrid"), ("Luis", "Sevilla"), ("Eva", "Madrid")]:
por_ciudad[ciudad].append(nombre) # no hace falta comprobar si la clave existe
print(dict(por_ciudad)) # {'Madrid': ['Ana', 'Eva'], 'Sevilla': ['Luis']}
itertools: combinar iterables
import itertools
print(list(itertools.combinations(["Ana", "Luis", "Eva"], 2)))
# [('Ana', 'Luis'), ('Ana', 'Eva'), ('Luis', 'Eva')] (parejas posibles)
print(list(itertools.chain([1, 2], [3], [4, 5]))) # [1, 2, 3, 4, 5]
statistics: estadística básica
import statistics
notas = [6, 7.5, 8, 5, 9, 7.5]
print(statistics.mean(notas)) # 7.166666666666667 (media)
print(statistics.median(notas)) # 7.5 (mediana)
print(statistics.mode(notas)) # 7.5 (moda)
Para explorar un módulo desde la consola interactiva, usa dir(math) para ver su contenido y help(math.sqrt) para leer la documentación de una función.
Dónde busca Python los módulos: sys.path
Al hacer import algo, Python busca en una lista de carpetas guardada en sys.path, en este orden:
- La carpeta del script que estás ejecutando.
- Las carpetas de la variable de entorno
PYTHONPATH, si existe. - La biblioteca estándar.
- La carpeta
site-packages, donde se instalan los paquetes externos con pip.
import sys
for carpeta in sys.path:
print(carpeta)
Si obtienes ModuleNotFoundError: No module named 'calculos', casi siempre es porque ejecutas el programa desde otra carpeta o el archivo no está donde crees. Si el módulo es externo (como requests), significa que no está instalado en el entorno que usas.
Cuidado: aunque se puede, no modifiques
sys.patha mano para “arreglar” un import. Organiza bien tu proyecto en paquetes y ejecútalo desde su carpeta raíz.
Buenas prácticas con los imports
- Pon todos los imports al principio del archivo, después del docstring del módulo.
- Agrúpalos en tres bloques separados por una línea en blanco: biblioteca estándar, paquetes externos y tus módulos.
- Un import por línea cuando son módulos distintos:
import oseimport sysen líneas separadas. - Prefiere
import moduloofrom modulo import nombreconcretos. Nuncaimport *. - Nombres de módulos cortos, en minúsculas y con guion bajo si hace falta:
gestion_pedidos.py.
"""Programa principal de la tienda."""
import json
import sys
from pathlib import Path
import requests
from tienda.productos import crear_producto
Errores frecuentes
- Llamar a tu archivo como un módulo estándar (
random.py,csv.py): tapa al original. ModuleNotFoundError: el archivo no está ensys.patho el paquete no está instalado en el entorno activo.- Olvidar el prefijo: tras
import math, escribirsqrt(4)daNameError; hay que ponermath.sqrt(4). - Código de prueba sin
if __name__ == "__main__": se ejecuta cada vez que alguien importa el módulo. - Imports circulares: si
a.pyimportab.pyyb.pyimportaa.py, puedes obtener errores raros. Suele indicar que hay que reorganizar el código.
Resumen
| Sintaxis | Qué hace |
|---|---|
import modulo | Importa el módulo; se usa como modulo.nombre |
from modulo import a, b | Trae nombres concretos para usarlos sin prefijo |
import modulo as m | Importa con un alias |
from .modulo import x | Import relativo dentro de un paquete |
if __name__ == "__main__": | Código que solo se ejecuta al lanzar el archivo directamente |
__init__.py | Marca una carpeta como paquete |
sys.path | Lista de carpetas donde Python busca los módulos |
Con la biblioteca estándar resuelves muchísimas tareas sin instalar nada. Cuando necesites más, instalarás paquetes externos con pip y entornos virtuales.
Pon a prueba lo que has aprendido
¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.