Módulos
Módulos en Python
Qué es un módulo
Un módulo es un archivo de Python con extensión .py que contiene variables, funciones y clases que puedes reutilizar en otros programas. En lugar de escribir todo el código en un solo archivo enorme, los módulos permiten dividir el programa en partes organizadas, cada una con una responsabilidad concreta.
Python viene con una enorme colección de módulos ya listos para usar llamada librería estándar. No necesitas instalar nada, solo importarlos.
Cómo importar un módulo
Hay varias formas de importar según lo que necesites:
# Importar el módulo completo — accedes con modulo.funcion()
import math
print(math.sqrt(25)) # 5.0
# Importar solo lo que necesitas — accedes directamente sin prefijo
from math import sqrt, pi
print(sqrt(25)) # 5.0
print(pi) # 3.141592653589793
# Importar todo el contenido — no recomendado porque puede generar conflictos
from math import *
print(sqrt(25)) # 5.0
# Importar con alias — útil cuando el nombre es largo
import datetime as dt
print(dt.datetime.now())
La forma más clara y recomendada es import modulo porque siempre sabes de dónde viene cada función cuando la usas.
1. Módulo math — operaciones matemáticas
Proporciona funciones matemáticas que van mucho más allá de los operadores básicos de Python.
Constantes
import math
print(math.pi) # 3.141592653589793 — el número π
print(math.e) # 2.718281828459045 — el número de Euler
print(math.inf) # inf — infinito
print(math.tau) # 6.283185307 — 2π
Raíces y potencias
import math
# Raíz cuadrada
print(math.sqrt(144)) # 12.0
print(math.sqrt(2)) # 1.4142135623730951
# Raíz cúbica — no existe directamente, se calcula con potencia
print(27 ** (1/3)) # 3.0
# Potencia con base e (exponencial)
print(math.exp(1)) # 2.718281828 → e¹
print(math.exp(2)) # 7.389056099 → e²
# Logaritmos
print(math.log(math.e)) # 1.0 → logaritmo natural
print(math.log(100, 10)) # 2.0 → log base 10
print(math.log2(8)) # 3.0 → log base 2
print(math.log10(1000)) # 3.0
Redondeo
import math
numero = 4.7
print(math.floor(numero)) # 4 → redondea hacia abajo
print(math.ceil(numero)) # 5 → redondea hacia arriba
print(round(numero)) # 5 → redondeo estándar
print(math.trunc(numero)) # 4 → elimina decimales sin redondear
print(math.floor(-4.7)) # -5 ← ojo con negativos
print(math.ceil(-4.7)) # -4
Trigonometría
import math
# Los ángulos se expresan en radianes, no en grados
angulo_grados = 90
angulo_radianes = math.radians(angulo_grados) # convierte grados a radianes
print(math.sin(angulo_radianes)) # 1.0
print(math.cos(math.radians(0))) # 1.0
print(math.tan(math.radians(45))) # 1.0
# Convertir radianes a grados
print(math.degrees(math.pi)) # 180.0
print(math.degrees(math.pi / 2)) # 90.0
Valor absoluto y factorial
import math
print(math.fabs(-7.5)) # 7.5 → valor absoluto siempre como float
print(abs(-7.5)) # 7.5 → versión built-in de Python
print(math.factorial(5)) # 120 → 5! = 5×4×3×2×1
print(math.factorial(0)) # 1 → 0! = 1 por definición
Ejemplo práctico — calculadora geométrica
import math
def area_circulo(radio):
return math.pi * radio ** 2
def hipotenusa(cateto_a, cateto_b):
return math.sqrt(cateto_a ** 2 + cateto_b ** 2)
def area_triangulo_angulo(lado_a, lado_b, angulo_grados):
angulo_rad = math.radians(angulo_grados)
return 0.5 * lado_a * lado_b * math.sin(angulo_rad)
print(f"Área círculo radio 5: {area_circulo(5):.2f}")
print(f"Hipotenusa de 3 y 4: {hipotenusa(3, 4):.2f}")
print(f"Área triángulo 6,8 a 30°: {area_triangulo_angulo(6, 8, 30):.2f}")
```
Salida:
```
Área círculo radio 5: 78.54
Hipotenusa de 3 y 4: 5.00
Área triángulo 6,8 a 30°: 12.00
2. Módulo random — números y elecciones aleatorias
Imprescindible para juegos, simulaciones, generación de datos de prueba y sorteos.
Números aleatorios
import random
# Entero aleatorio entre dos valores (ambos incluidos)
print(random.randint(1, 10)) # por ejemplo: 7
# Decimal aleatorio entre 0.0 y 1.0
print(random.random()) # por ejemplo: 0.374...
# Decimal aleatorio entre dos valores
print(random.uniform(1.5, 9.5)) # por ejemplo: 6.234...
# Entero en un rango con paso (igual que range)
print(random.randrange(0, 101, 5)) # múltiplo de 5 entre 0 y 100
Elecciones sobre secuencias
import random
opciones = ["roca", "papel", "tijera"]
# Elegir un elemento aleatorio
print(random.choice(opciones)) # por ejemplo: "papel"
# Elegir varios elementos sin repetición
print(random.sample(opciones, 2)) # por ejemplo: ["tijera", "roca"]
# Elegir varios elementos con posible repetición
print(random.choices(opciones, k=4)) # por ejemplo: ["papel", "papel", "roca", "tijera"]
# Elegir con pesos (probabilidades distintas)
pesos = [50, 30, 20] # 50% roca, 30% papel, 20% tijera
print(random.choices(opciones, weights=pesos, k=1))
Mezclar y reproducibilidad
import random
baraja = list(range(1, 53))
random.shuffle(baraja) # mezcla la lista en sitio (no devuelve nada)
print(baraja[:5]) # primeras 5 cartas tras mezclar
# Semilla — para reproducir siempre los mismos resultados
random.seed(42)
print(random.randint(1, 100)) # siempre da el mismo valor con la misma semilla
print(random.randint(1, 100)) # este también
random.seed(42) # reseteamos la semilla
print(random.randint(1, 100)) # mismo valor que antes
Ejemplo práctico — simulador de dados y lotería
import random
def lanzar_dados(num_dados=2, caras=6):
resultados = [random.randint(1, caras) for _ in range(num_dados)]
return resultados, sum(resultados)
def generar_loteria(numeros=6, maximo=49):
return sorted(random.sample(range(1, maximo + 1), numeros))
def simular_moneda(lanzamientos=10):
resultados = random.choices(["cara", "cruz"], k=lanzamientos)
caras = resultados.count("cara")
cruces = resultados.count("cruz")
return caras, cruces
# Pruebas
dados, total = lanzar_dados(2, 6)
print(f"Dados: {dados} → Total: {total}")
print(f"Lotería: {generar_loteria()}")
caras, cruces = simular_moneda(100)
print(f"100 lanzamientos: {caras} caras, {cruces} cruces")
```
Salida (varía en cada ejecución):
```
Dados: [3, 5] → Total: 8
Lotería: [4, 12, 23, 31, 38, 45]
100 lanzamientos: 53 caras, 47 cruces
3. Módulo datetime — fechas y horas
Fundamental para cualquier aplicación que trabaje con tiempo: registros, calendarios, plazos, etc.
Fecha y hora actual
from datetime import datetime, date, time, timedelta
# Fecha y hora completa
ahora = datetime.now()
print(ahora) # 2024-01-15 14:32:05.123456
print(ahora.year) # 2024
print(ahora.month) # 1
print(ahora.day) # 15
print(ahora.hour) # 14
print(ahora.minute) # 32
print(ahora.second) # 5
# Solo fecha
hoy = date.today()
print(hoy) # 2024-01-15
# Solo hora
hora_actual = datetime.now().time()
print(hora_actual) # 14:32:05.123456
Crear fechas específicas
from datetime import datetime, date
# Fecha y hora completa
mi_fecha = datetime(2024, 6, 15, 10, 30, 0)
print(mi_fecha) # 2024-06-15 10:30:00
# Solo fecha
cumpleanos = date(1995, 4, 22)
print(cumpleanos) # 1995-04-22
Operaciones con fechas — timedelta
from datetime import datetime, timedelta
ahora = datetime.now()
# Sumar tiempo
manana = ahora + timedelta(days=1)
en_una_hora = ahora + timedelta(hours=1)
en_dos_semanas = ahora + timedelta(weeks=2)
print(f"Mañana: {manana.strftime('%d/%m/%Y')}")
print(f"En una hora: {en_una_hora.strftime('%H:%M')}")
# Restar fechas — el resultado es un timedelta
fecha_inicio = datetime(2024, 1, 1)
fecha_fin = datetime(2024, 12, 31)
diferencia = fecha_fin - fecha_inicio
print(f"Días del año: {diferencia.days}") # 365
Formatear fechas con strftime
from datetime import datetime
ahora = datetime.now()
# strftime convierte fecha a string con el formato que quieras
print(ahora.strftime("%d/%m/%Y")) # 15/01/2024
print(ahora.strftime("%d de %B de %Y")) # 15 de January de 2024
print(ahora.strftime("%H:%M:%S")) # 14:32:05
print(ahora.strftime("%A, %d de %B")) # Monday, 15 de January
print(ahora.strftime("%Y-%m-%d %H:%M")) # 2024-01-15 14:32
Códigos de formato más usados:
| Código | Significado | Ejemplo |
|---|---|---|
%d |
Día con cero | 05 |
%m |
Mes con cero | 01 |
%Y |
Año completo | 2024 |
%H |
Hora 24h | 14 |
%M |
Minutos | 32 |
%S |
Segundos | 05 |
%A |
Día semana | Monday |
%B |
Mes en texto | January |
Parsear strings a fechas con strptime
from datetime import datetime
# strptime convierte string a fecha
texto = "15/01/2024"
fecha = datetime.strptime(texto, "%d/%m/%Y")
print(fecha) # 2024-01-15 00:00:00
print(type(fecha)) # <class 'datetime.datetime'>
# Ahora puedes operar con ella
print(fecha.year) # 2024
Ejemplo práctico — calculadora de edad y plazos
from datetime import datetime, date
def calcular_edad(fecha_nacimiento_str):
nacimiento = datetime.strptime(fecha_nacimiento_str, "%d/%m/%Y").date()
hoy = date.today()
edad = hoy.year - nacimiento.year
if (hoy.month, hoy.day) < (nacimiento.month, nacimiento.day):
edad -= 1
return edad
def dias_hasta(fecha_str):
objetivo = datetime.strptime(fecha_str, "%d/%m/%Y").date()
hoy = date.today()
diferencia = objetivo - hoy
return diferencia.days
def es_fin_de_semana():
return date.today().weekday() >= 5 # 5=sábado, 6=domingo
print(f"Edad: {calcular_edad('15/04/1995')} años")
print(f"Días hasta Navidad: {dias_hasta('25/12/2024')}")
print(f"¿Es fin de semana? {'Sí' if es_fin_de_semana() else 'No'}")
4. Módulo os — interacción con el sistema operativo
Permite gestionar archivos, directorios y variables de entorno de forma independiente del sistema operativo.
Directorio de trabajo
import os
# Directorio actual
print(os.getcwd()) # /home/usuario/proyecto
# Cambiar de directorio
os.chdir("/home/usuario")
print(os.getcwd()) # /home/usuario
Gestión de archivos y directorios
import os
# Listar contenido de un directorio
archivos = os.listdir(".") # "." es el directorio actual
print(archivos) # ['archivo.py', 'datos', 'readme.txt']
# Crear directorio
os.mkdir("nueva_carpeta")
# Crear directorio y todos los intermedios
os.makedirs("carpeta/subcarpeta/sub_sub")
# Eliminar archivo
os.remove("archivo_viejo.txt")
# Eliminar directorio vacío
os.rmdir("carpeta_vacia")
# Renombrar o mover
os.rename("viejo.txt", "nuevo.txt")
# Comprobar si existe
print(os.path.exists("archivo.txt")) # True o False
print(os.path.isfile("archivo.txt")) # True si es archivo
print(os.path.isdir("carpeta")) # True si es directorio
Rutas con os.path
import os
# Unir rutas de forma segura (funciona en Windows y Linux)
ruta = os.path.join("usuarios", "ana", "documentos", "informe.pdf")
print(ruta) # usuarios/ana/documentos/informe.pdf (Linux)
# usuarios\ana\documentos\informe.pdf (Windows)
# Separar nombre y extensión
nombre, extension = os.path.splitext("informe.pdf")
print(nombre) # informe
print(extension) # .pdf
# Obtener solo el nombre del archivo
print(os.path.basename("/ruta/completa/archivo.txt")) # archivo.txt
# Obtener solo el directorio
print(os.path.dirname("/ruta/completa/archivo.txt")) # /ruta/completa
# Tamaño del archivo en bytes
print(os.path.getsize("archivo.txt"))
Variables de entorno
import os
# Leer variable de entorno
usuario = os.environ.get("USER", "desconocido")
print(f"Usuario del sistema: {usuario}")
# Establecer variable de entorno
os.environ["MI_VARIABLE"] = "mi_valor"
print(os.environ.get("MI_VARIABLE")) # mi_valor
Ejemplo práctico — organizador de archivos
import os
def listar_archivos_por_extension(directorio="."):
archivos_por_tipo = {}
for archivo in os.listdir(directorio):
ruta_completa = os.path.join(directorio, archivo)
if os.path.isfile(ruta_completa):
nombre, ext = os.path.splitext(archivo)
ext = ext.lower() if ext else "sin extensión"
if ext not in archivos_por_tipo:
archivos_por_tipo[ext] = []
archivos_por_tipo[ext].append(archivo)
for ext, archivos in sorted(archivos_por_tipo.items()):
print(f"{ext:<15} → {len(archivos)} archivo(s)")
for archivo in archivos:
tamaño = os.path.getsize(os.path.join(directorio, archivo))
print(f" {archivo} ({tamaño} bytes)")
listar_archivos_por_extension(".")
5. Módulo json — trabajar con datos JSON
JSON (JavaScript Object Notation) es el formato de intercambio de datos más usado en APIs y configuraciones.
Convertir Python a JSON
import json
datos = {
"nombre": "Ana García",
"edad": 22,
"notas": [8.5, 9.0, 7.8],
"activa": True,
"direccion": None
}
# Convertir a string JSON
json_texto = json.dumps(datos)
print(json_texto)
# {"nombre": "Ana Garc\u00eda", "edad": 22, "notas": [8.5, 9.0, 7.8], ...}
# Con formato legible
json_bonito = json.dumps(datos, indent=4, ensure_ascii=False)
print(json_bonito)
Salida de json_bonito:
{
"nombre": "Ana García",
"edad": 22,
"notas": [8.5, 9.0, 7.8],
"activa": true,
"direccion": null
}
Convertir JSON a Python
import json
texto_json = '{"nombre": "Carlos", "edad": 30, "ciudad": "Madrid"}'
datos = json.loads(texto_json)
print(datos["nombre"]) # Carlos
print(type(datos)) # <class 'dict'>
Leer y escribir archivos JSON
import json
# Escribir en archivo
alumnos = [
{"nombre": "Ana", "nota": 8.5},
{"nombre": "Carlos", "nota": 6.0}
]
with open("alumnos.json", "w", encoding="utf-8") as archivo:
json.dump(alumnos, archivo, indent=4, ensure_ascii=False)
# Leer desde archivo
with open("alumnos.json", "r", encoding="utf-8") as archivo:
datos_leidos = json.load(archivo)
for alumno in datos_leidos:
print(f"{alumno['nombre']}: {alumno['nota']}")
Equivalencias Python ↔ JSON
| Python | JSON |
|---|---|
dict |
object {} |
list, tuple |
array [] |
str |
string "" |
int, float |
number |
True |
true |
False |
false |
None |
null |
Ejemplo práctico — sistema de configuración
import json
import os
def cargar_config(archivo="config.json"):
config_default = {
"idioma": "es",
"tema": "claro",
"max_intentos": 3,
"mostrar_ayuda": True
}
if not os.path.exists(archivo):
guardar_config(config_default, archivo)
return config_default
with open(archivo, "r", encoding="utf-8") as f:
return json.load(f)
def guardar_config(config, archivo="config.json"):
with open(archivo, "w", encoding="utf-8") as f:
json.dump(config, f, indent=4, ensure_ascii=False)
print(f"Configuración guardada en {archivo}")
def actualizar_config(clave, valor, archivo="config.json"):
config = cargar_config(archivo)
config[clave] = valor
guardar_config(config, archivo)
print(f"'{clave}' actualizado a '{valor}'")
config = cargar_config()
print(f"Idioma actual: {config['idioma']}")
actualizar_config("tema", "oscuro")
6. Otros módulos importantes
sys — información del sistema
import sys
print(sys.version) # versión de Python
print(sys.platform) # sistema operativo: 'linux', 'win32', 'darwin'
print(sys.argv) # argumentos de línea de comandos
# Terminar el programa con un código de salida
# sys.exit(0) # 0 = éxito, otro número = error
time — medición de tiempo
import time
# Tiempo actual en segundos desde el 1 de enero de 1970
print(time.time()) # 1705312325.123456
# Pausar la ejecución
print("Iniciando...")
time.sleep(2) # pausa 2 segundos
print("Han pasado 2 segundos")
# Medir cuánto tarda un código
inicio = time.time()
suma = sum(range(1_000_000))
fin = time.time()
print(f"Calculado en {fin - inicio:.4f} segundos")
collections — estructuras de datos avanzadas
from collections import Counter, defaultdict, deque
# Counter — cuenta elementos
palabras = ["python", "es", "genial", "python", "mola", "python"]
conteo = Counter(palabras)
print(conteo) # Counter({'python': 3, 'es': 1, ...})
print(conteo.most_common(2)) # [('python', 3), ('es', 1)]
# defaultdict — diccionario con valor por defecto
notas = defaultdict(list)
notas["Ana"].append(8.5) # no da error aunque "Ana" no existiera
notas["Ana"].append(9.0)
print(notas["Ana"]) # [8.5, 9.0]
# deque — cola doble eficiente
cola = deque([1, 2, 3])
cola.appendleft(0) # añade al inicio
cola.append(4) # añade al final
cola.popleft() # elimina del inicio
print(cola) # deque([1, 2, 3, 4])
string — constantes de caracteres
import string
print(string.ascii_letters) # abcdefghijklmnopqrstuvwxyzABCDEF...
print(string.ascii_lowercase) # abcdefghijklmnopqrstuvwxyz
print(string.ascii_uppercase) # ABCDEFGHIJKLMNOPQRSTUVWXYZ
print(string.digits) # 0123456789
print(string.punctuation) # !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
# Uso real: generar contraseña aleatoria
import random
import string
def generar_contrasena(longitud=12):
caracteres = string.ascii_letters + string.digits + string.punctuation
return "".join(random.choice(caracteres) for _ in range(longitud))
print(generar_contrasena()) # por ejemplo: aB3#mK9@pL2!
7. Crear tus propios módulos
Cualquier archivo .py es un módulo que puedes importar desde otro archivo.
archivo: utilidades.py
# Este archivo ES el módulo
PI = 3.14159
def saludar(nombre):
return f"Hola, {nombre}!"
def calcular_area_circulo(radio):
return PI * radio ** 2
def calcular_media(numeros):
if not numeros:
return 0
return sum(numeros) / len(numeros)
archivo: mi_programa.py
# Importamos nuestro módulo
import utilidades
print(utilidades.saludar("Ana"))
print(utilidades.calcular_area_circulo(5))
print(utilidades.calcular_media([8, 6, 9, 7]))
# O importando solo lo que necesitamos
from utilidades import calcular_media, PI
print(calcular_media([5, 7, 8]))
print(PI)
El bloque if __name__ == "__main__"
Cuando Python ejecuta un archivo directamente, la variable __name__ vale "__main__". Cuando ese mismo archivo se importa como módulo, __name__ vale el nombre del archivo. Esto permite tener código de prueba que solo se ejecuta cuando corres el archivo directamente pero no cuando lo importas:
# utilidades.py
def calcular_media(numeros):
return sum(numeros) / len(numeros)
# Este bloque SOLO se ejecuta si corres este archivo directamente
# NO se ejecuta si lo importas desde otro archivo
if __name__ == "__main__":
print("Probando el módulo...")
print(calcular_media([8, 6, 9])) # 7.666...
print("Todo correcto.")
Resumen
| Módulo | Para qué sirve | Funciones clave |
|---|---|---|
math |
Matemáticas avanzadas | sqrt, pi, sin, floor, ceil, factorial |
random |
Aleatoriedad | randint, choice, shuffle, sample, seed |
datetime |
Fechas y horas | now, today, strftime, strptime, timedelta |
os |
Sistema operativo | getcwd, listdir, mkdir, path.join, path.exists |
json |
Datos JSON | dumps, loads, dump, load |
sys |
Sistema Python | version, platform, argv, exit |
time |
Medición de tiempo | time, sleep |
collections |
Estructuras avanzadas | Counter, defaultdict, deque |
string |
Constantes de texto | ascii_letters, digits, punctuation |