📚 Unidad 7. Módulos y Paquetes
Los módulos y paquetes permiten organizar y reutilizar código en Python. Un módulo es un archivo .py con código, y un paquete es una carpeta con módulos.
7.1. Importar Módulos
Import Básico
# Importar módulo completo
import math
# Usar funciones del módulo
print(math.sqrt(16)) # 4.0
print(math.pi) # 3.141592653589793
print(math.ceil(4.2)) # 5
print(math.floor(4.8)) # 4
Import con Alias
Importar Elementos Específicos
Importar con Alias Específico
Importar Todo (No Recomendado)
from math import *
print(sqrt(64)) # 8.0
print(sin(0)) # 0.0
# No se recomienda porque puede causar conflictos de nombres
7.2. Módulos de la Biblioteca Estándar
Python incluye muchos módulos útiles.
Módulo math - Matemáticas
import math
# Constantes
print(math.pi) # 3.141592653589793
print(math.e) # 2.718281828459045
print(math.tau) # 6.283185307179586 (2π)
# Funciones básicas
print(math.sqrt(16)) # 4.0 (raíz cuadrada)
print(math.pow(2, 8)) # 256.0 (potencia)
print(math.factorial(5)) # 120 (5!)
# Redondeo
print(math.ceil(4.1)) # 5 (hacia arriba)
print(math.floor(4.9)) # 4 (hacia abajo)
print(math.trunc(4.7)) # 4 (truncar)
# Trigonometría (en radianes)
print(math.sin(math.pi/2)) # 1.0
print(math.cos(0)) # 1.0
print(math.degrees(math.pi)) # 180.0 (radianes a grados)
print(math.radians(180)) # 3.14159... (grados a radianes)
# Logaritmos
print(math.log(10)) # 2.302... (ln)
print(math.log10(100)) # 2.0
print(math.log2(8)) # 3.0
Módulo random - Números Aleatorios
import random
# Número aleatorio
print(random.random()) # Float entre 0 y 1
print(random.uniform(1, 10)) # Float entre 1 y 10
print(random.randint(1, 100)) # Entero entre 1 y 100 (incluidos)
# Elegir de una secuencia
colores = ["rojo", "verde", "azul"]
print(random.choice(colores)) # Un elemento al azar
# Múltiples elecciones
print(random.choices(colores, k=5)) # 5 elementos (con repetición)
print(random.sample(range(1, 50), k=6)) # 6 elementos (sin repetición)
# Mezclar lista
numeros = [1, 2, 3, 4, 5]
random.shuffle(numeros) # Mezcla in-place
print(numeros)
# Semilla para reproducibilidad
random.seed(42)
print(random.randint(1, 100)) # Siempre da el mismo resultado
Módulo datetime - Fechas y Horas
from datetime import datetime, date, time, timedelta
# Fecha y hora actual
ahora = datetime.now()
print(ahora) # 2026-01-15 10:30:45.123456
# Solo fecha
hoy = date.today()
print(hoy) # 2026-01-15
# Crear fecha específica
mi_fecha = date(2026, 12, 25)
print(mi_fecha) # 2026-12-25
# Crear datetime específico
mi_datetime = datetime(2026, 12, 25, 18, 30)
print(mi_datetime) # 2026-12-25 18:30:00
# Acceder a componentes
print(ahora.year) # 2026
print(ahora.month) # 1
print(ahora.day) # 15
print(ahora.hour) # 10
print(ahora.minute) # 30
# Formatear fechas
print(ahora.strftime("%d/%m/%Y")) # 15/01/2026
print(ahora.strftime("%H:%M:%S")) # 10:30:45
print(ahora.strftime("%A, %d de %B")) # Wednesday, 15 de January
# Parsear strings a fechas
fecha_str = "25/12/2026"
fecha = datetime.strptime(fecha_str, "%d/%m/%Y")
print(fecha) # 2026-12-25 00:00:00
# Operaciones con fechas
manana = hoy + timedelta(days=1)
hace_una_semana = hoy - timedelta(weeks=1)
en_dos_horas = ahora + timedelta(hours=2)
# Diferencia entre fechas
navidad = date(2026, 12, 25)
dias_restantes = navidad - hoy
print(f"Faltan {dias_restantes.days} días para Navidad")
Módulo os - Sistema Operativo
import os
# Directorio actual
print(os.getcwd()) # C:\Users\...
# Cambiar directorio
# os.chdir("/ruta/nueva")
# Listar archivos
archivos = os.listdir(".")
print(archivos)
# Verificar existencia
print(os.path.exists("archivo.txt"))
print(os.path.isfile("archivo.txt"))
print(os.path.isdir("carpeta"))
# Crear directorio
# os.mkdir("nueva_carpeta") # Una carpeta
# os.makedirs("ruta/nueva/completa") # Varias carpetas
# Eliminar
# os.remove("archivo.txt") # Archivo
# os.rmdir("carpeta_vacia") # Carpeta vacía
# Variables de entorno
print(os.environ.get("PATH"))
print(os.environ.get("HOME"))
# Información del sistema
print(os.name) # 'nt' (Windows) o 'posix' (Linux/Mac)
print(os.sep) # '\' (Windows) o '/' (Linux/Mac)
# Rutas
ruta = os.path.join("carpeta", "subcarpeta", "archivo.txt")
print(ruta) # carpeta\subcarpeta\archivo.txt
print(os.path.basename("/ruta/al/archivo.txt")) # archivo.txt
print(os.path.dirname("/ruta/al/archivo.txt")) # /ruta/al
print(os.path.splitext("documento.pdf")) # ('documento', '.pdf')
Módulo sys - Sistema
import sys
# Versión de Python
print(sys.version) # 3.12.0 ...
print(sys.version_info) # (3, 12, 0, 'final', 0)
# Argumentos de línea de comandos
# python script.py arg1 arg2
print(sys.argv) # ['script.py', 'arg1', 'arg2']
# Rutas de búsqueda de módulos
print(sys.path)
# Salir del programa
# sys.exit(0) # 0 = éxito, otro número = error
Módulo json - JSON
import json
# Diccionario a JSON (serializar)
datos = {
"nombre": "Ana",
"edad": 30,
"ciudades": ["Madrid", "Barcelona"]
}
json_str = json.dumps(datos)
print(json_str) # {"nombre": "Ana", "edad": 30, ...}
# Con formato legible
json_bonito = json.dumps(datos, indent=4, ensure_ascii=False)
print(json_bonito)
# JSON a diccionario (deserializar)
json_texto = '{"nombre": "Luis", "edad": 25}'
datos = json.loads(json_texto)
print(datos["nombre"]) # Luis
# Guardar JSON en archivo
with open("datos.json", "w") as f:
json.dump(datos, f, indent=4)
# Leer JSON de archivo
with open("datos.json", "r") as f:
datos_leidos = json.load(f)
Módulo re - Expresiones Regulares
import re
texto = "Mi email es usuario@ejemplo.com y mi teléfono 612345678"
# Buscar patrón
resultado = re.search(r"\d+", texto) # Buscar dígitos
if resultado:
print(resultado.group()) # 612345678
# Encontrar todos
emails = "contacto@ejemplo.com, info@empresa.es"
patron_email = r"\b[\w.-]+@[\w.-]+\.\w+\b"
encontrados = re.findall(patron_email, emails)
print(encontrados) # ['contacto@ejemplo.com', 'info@empresa.es']
# Reemplazar
texto = "Hola 123 Mundo 456"
limpio = re.sub(r"\d+", "XXX", texto)
print(limpio) # Hola XXX Mundo XXX
# Validar formato
def validar_email(email):
patron = r"^[\w.-]+@[\w.-]+\.\w{2,}$"
return bool(re.match(patron, email))
print(validar_email("test@ejemplo.com")) # True
print(validar_email("invalido")) # False
Módulo collections - Colecciones Especiales
from collections import Counter, defaultdict, namedtuple, deque
# Counter - Contar elementos
palabras = ["a", "b", "a", "c", "a", "b"]
contador = Counter(palabras)
print(contador) # Counter({'a': 3, 'b': 2, 'c': 1})
print(contador.most_common(2)) # [('a', 3), ('b', 2)]
# defaultdict - Diccionario con valor por defecto
dd = defaultdict(list)
dd["frutas"].append("manzana")
dd["frutas"].append("naranja")
dd["verduras"].append("zanahoria")
print(dict(dd)) # {'frutas': ['manzana', 'naranja'], 'verduras': ['zanahoria']}
# namedtuple - Tupla con nombres
Punto = namedtuple("Punto", ["x", "y"])
p = Punto(10, 20)
print(p.x, p.y) # 10 20
# deque - Cola de doble extremo (eficiente)
cola = deque([1, 2, 3])
cola.append(4) # Añadir al final
cola.appendleft(0) # Añadir al inicio
print(cola) # deque([0, 1, 2, 3, 4])
7.3. Crear Módulos Propios
Módulo Simple
Crea un archivo mi_modulo.py:
# mi_modulo.py
"""Mi módulo personalizado con funciones útiles."""
PI = 3.14159
def saludar(nombre):
"""Saluda a una persona."""
return f"¡Hola, {nombre}!"
def area_circulo(radio):
"""Calcula el área de un círculo."""
return PI * radio ** 2
def es_par(numero):
"""Verifica si un número es par."""
return numero % 2 == 0
Usa el módulo en otro archivo:
# main.py
import mi_modulo
print(mi_modulo.saludar("Ana"))
print(mi_modulo.area_circulo(5))
print(mi_modulo.PI)
# O importar específico
from mi_modulo import saludar, es_par
print(saludar("Luis"))
print(es_par(7)) # False
Bloque __name__
# calculadora.py
def sumar(a, b):
return a + b
def restar(a, b):
return a - b
# Código que solo se ejecuta si se ejecuta este archivo directamente
if __name__ == "__main__":
# Pruebas
print("Probando calculadora...")
print(f"5 + 3 = {sumar(5, 3)}")
print(f"10 - 4 = {restar(10, 4)}")
Si ejecutas python calculadora.py, se ejecutan las pruebas.
Si haces import calculadora, las pruebas NO se ejecutan.
7.4. Crear Paquetes
Un paquete es una carpeta con un archivo __init__.py.
Estructura de Paquete
Contenido de los Archivos
mi_paquete/__init__.py:
"""Mi paquete de utilidades."""
from .matematicas import sumar, restar
from .texto import mayusculas
mi_paquete/matematicas.py:
mi_paquete/texto.py:
def mayusculas(texto):
return texto.upper()
def minusculas(texto):
return texto.lower()
def invertir(texto):
return texto[::-1]
Usar el Paquete
# Importar desde el paquete
import mi_paquete
print(mi_paquete.sumar(5, 3))
# Importar módulo específico
from mi_paquete import matematicas
print(matematicas.multiplicar(4, 5))
# Importar función específica
from mi_paquete.texto import invertir
print(invertir("Python")) # nohtyP
# Importar subpaquete
from mi_paquete.utilidades import archivos
7.5. Gestión de Paquetes con pip
pip es el gestor de paquetes de Python.
Comandos Básicos
# Ver versión de pip
pip --version
# Instalar paquete
pip install nombre_paquete
pip install numpy
pip install pandas==1.5.0 # Versión específica
# Desinstalar paquete
pip uninstall nombre_paquete
# Actualizar paquete
pip install --upgrade nombre_paquete
# Ver paquetes instalados
pip list
# Información de un paquete
pip show numpy
# Buscar paquetes (en PyPI)
pip search nombre # Nota: puede estar deshabilitado
Archivo requirements.txt
# Crear archivo con dependencias actuales
pip freeze > requirements.txt
# Instalar desde requirements.txt
pip install -r requirements.txt
Ejemplo de requirements.txt:
7.6. Entornos Virtuales
Los entornos virtuales aíslan las dependencias de cada proyecto.
Crear Entorno Virtual
Activar Entorno
Desactivar Entorno
Flujo de Trabajo Típico
# 1. Crear entorno
python -m venv venv
# 2. Activar
venv\Scripts\activate # Windows
# 3. Instalar dependencias
pip install numpy pandas matplotlib
# 4. Guardar dependencias
pip freeze > requirements.txt
# 5. Trabajar en el proyecto...
# 6. Desactivar cuando termines
deactivate
Estructura de Proyecto Recomendada
mi_proyecto/
venv/ # Entorno virtual (no subir a Git)
src/ # Código fuente
__init__.py
main.py
utils.py
tests/ # Pruebas
test_main.py
requirements.txt # Dependencias
README.md
.gitignore
.gitignore típico:
7.7. Ejercicios Prácticos
Ejercicio 1: Generador de Contraseñas
import random
import string
def generar_contrasena(longitud=12, incluir_mayusculas=True,
incluir_numeros=True, incluir_simbolos=True):
"""
Genera una contraseña aleatoria.
Args:
longitud: Longitud de la contraseña
incluir_mayusculas: Si incluir letras mayúsculas
incluir_numeros: Si incluir dígitos
incluir_simbolos: Si incluir símbolos especiales
Returns:
str: Contraseña generada
"""
caracteres = string.ascii_lowercase # a-z
if incluir_mayusculas:
caracteres += string.ascii_uppercase # A-Z
if incluir_numeros:
caracteres += string.digits # 0-9
if incluir_simbolos:
caracteres += string.punctuation # !@#$%...
contrasena = ''.join(random.choice(caracteres) for _ in range(longitud))
return contrasena
# Generar varias contraseñas
print("Contraseñas generadas:")
for i in range(5):
print(f" {i+1}. {generar_contrasena()}")
# Contraseña solo con letras y números
print(f"\nSin símbolos: {generar_contrasena(16, incluir_simbolos=False)}")
Ejercicio 2: Análisis de Fechas
from datetime import datetime, timedelta
def dias_entre_fechas(fecha1_str, fecha2_str, formato="%d/%m/%Y"):
"""Calcula días entre dos fechas."""
fecha1 = datetime.strptime(fecha1_str, formato)
fecha2 = datetime.strptime(fecha2_str, formato)
diferencia = abs((fecha2 - fecha1).days)
return diferencia
def edad(fecha_nacimiento_str, formato="%d/%m/%Y"):
"""Calcula la edad en años."""
nacimiento = datetime.strptime(fecha_nacimiento_str, formato)
hoy = datetime.now()
edad = hoy.year - nacimiento.year
# Ajustar si no ha llegado el cumpleaños este año
if (hoy.month, hoy.day) < (nacimiento.month, nacimiento.day):
edad -= 1
return edad
def siguiente_cumpleanos(fecha_nacimiento_str, formato="%d/%m/%Y"):
"""Calcula días hasta el próximo cumpleaños."""
nacimiento = datetime.strptime(fecha_nacimiento_str, formato)
hoy = datetime.now()
# Cumpleaños este año
cumple_este_ano = nacimiento.replace(year=hoy.year)
# Si ya pasó, calcular para el próximo año
if cumple_este_ano.date() < hoy.date():
cumple_este_ano = nacimiento.replace(year=hoy.year + 1)
dias = (cumple_este_ano.date() - hoy.date()).days
return dias
# Pruebas
print(f"Días entre fechas: {dias_entre_fechas('01/01/2020', '31/12/2020')}")
print(f"Mi edad: {edad('15/06/1990')}")
print(f"Días hasta mi cumpleaños: {siguiente_cumpleanos('15/06/1990')}")
Ejercicio 3: Módulo de Estadísticas
Crea estadisticas.py:
"""Módulo de estadísticas básicas."""
def media(datos):
"""Calcula la media aritmética."""
if not datos:
return None
return sum(datos) / len(datos)
def mediana(datos):
"""Calcula la mediana."""
if not datos:
return None
ordenados = sorted(datos)
n = len(ordenados)
medio = n // 2
if n % 2 == 0:
return (ordenados[medio - 1] + ordenados[medio]) / 2
return ordenados[medio]
def moda(datos):
"""Calcula la moda."""
if not datos:
return None
from collections import Counter
contador = Counter(datos)
max_freq = max(contador.values())
modas = [k for k, v in contador.items() if v == max_freq]
return modas[0] if len(modas) == 1 else modas
def varianza(datos):
"""Calcula la varianza."""
if not datos:
return None
m = media(datos)
return sum((x - m) ** 2 for x in datos) / len(datos)
def desviacion_estandar(datos):
"""Calcula la desviación estándar."""
var = varianza(datos)
return var ** 0.5 if var is not None else None
def resumen(datos):
"""Genera un resumen estadístico."""
return {
"n": len(datos),
"min": min(datos),
"max": max(datos),
"media": media(datos),
"mediana": mediana(datos),
"moda": moda(datos),
"desv_std": desviacion_estandar(datos)
}
if __name__ == "__main__":
# Pruebas
datos = [4, 7, 2, 9, 4, 1, 4, 8, 3, 4]
print("Datos:", datos)
for clave, valor in resumen(datos).items():
print(f" {clave}: {valor}")
7.8. Resumen
| Concepto | Ejemplo |
|---|---|
| Import módulo | import math |
| Import con alias | import numpy as np |
| Import específico | from math import sqrt |
| Crear módulo | Archivo .py con funciones |
| Crear paquete | Carpeta con __init__.py |
| Instalar paquete | pip install nombre |
| Entorno virtual | python -m venv venv |
| Activar entorno | venv\Scripts\activate |
📅 Fecha de creación: Enero 2026
✍️ Autor: Fran García