Módulos y la biblioteca estándar

Python viene con una enorme colección de herramientas listas para usar: aleatoriedad, matemáticas, fechas, rutas de archivos y mucho más. Estas herramientas viven en módulos, y las traes a tu código con import. Ya has usado import json en el capítulo Archivos y excepciones. Este capítulo cubre completamente las importaciones e introduce las partes más útiles de la biblioteca estándar.
Importar módulos
La importación más simple trae un módulo completo y te permite usar su contenido con notación de punto. También puedes importar nombres específicos de un módulo para usarlos directamente sin el prefijo. Los alias acortan nombres largos.
import math
math.sqrt(16) # 4.0
math.pi # 3.141592653589793
math.floor(3.9) # 3
math.ceil(3.1) # 4Importa nombres específicos de un módulo para que puedas usarlos directamente:
from math import sqrt, pi
sqrt(16) # 4.0 (no se necesita el prefijo "math.")
pi # 3.141592653589793Dale a un módulo o nombre un alias para acortarlo:
import math as m
m.sqrt(16) # 4.0
from math import sqrt as square_root
square_root(25) # 5.0Los alias son comunes con bibliotecas populares de terceros (import numpy as np, import pandas as pd). Para módulos de la biblioteca estándar, prefiere usar el nombre completo; hace que el código sea más legible.
import math trae el módulo completo, luego accedes dentro con un punto: math.sqrt(16). from math import sqrt toma un nombre para que puedas omitir el prefijo. La palabra clave as renombra una importación larga, pero para contenido de la biblioteca estándar el nombre completo se lee más claro. random
El módulo random genera números aleatorios y hace selecciones aleatorias. Úsalo para juegos, simulaciones, muestreo aleatorio y cualquier otra cosa que necesite impredecibilidad. Establecer una semilla hace que los resultados sean reproducibles: la misma semilla produce la misma secuencia cada vez.
import random
random.random() # float entre 0 y 1 (exclusivo)
random.randint(1, 10) # entero de 1 a 10 (ambos inclusivos)
random.uniform(1.0, 10.0) # float entre 1.0 y 10.0
colores = ["rojo", "verde", "azul"]
random.choice(colores) # elige un elemento
random.choices(colores, k=3) # elige k elementos (con reemplazo)
random.sample(colores, k=2) # elige k elementos (sin reemplazo)
numeros = [1, 2, 3, 4, 5]
random.shuffle(numeros) # mezcla en su lugar, devuelve NonePara resultados reproducibles (útil en pruebas y ciencia de datos), establece una semilla antes de generar:
random.seed(42)
random.randint(1, 100) # siempre el mismo valor para la semilla 42La misma semilla produce la misma secuencia cada vez, en cualquier máquina.
random.choice() elige un elemento de una lista, random.randint(1, 10) da un número entero en un rango, final incluido. ¿Quieres los mismos resultados cada ejecución, digamos para una prueba? Llama a random.seed() primero y la secuencia se bloquea. math
El módulo math añade operaciones matemáticas más avanzadas más allá de los operadores aritméticos básicos que conociste en el capítulo Números. Raíces cuadradas, potencias, logaritmos, trigonometría, y valores especiales como pi e infinito están todos aquí.
import math
math.sqrt(25) # 5.0
math.pow(2, 10) # 1024.0 (igual que 2 ** 10 pero siempre devuelve float)
math.log(100, 10) # 2.0 (log base 10)
math.log(math.e) # 1.0 (log natural)
math.sin(math.pi / 2) # 1.0
math.cos(0) # 1.0
math.ceil(3.2) # 4
math.floor(3.9) # 3
math.trunc(3.9) # 3 (igual que int() para positivos)
math.inf # infinito
math.isnan(float("nan")) # True
math.isinf(math.inf) # Truemath cubre todo más allá de + - * /: raíces cuadradas, potencias, logs, trig, más constantes como math.pi. Recurre a él en el momento en que un cálculo necesita más que los operadores básicos, y omites escribir la fórmula tú mismo. datetime
El módulo datetime maneja fechas y horas. datetime.now() te da la fecha y hora actual. strftime() la formatea como una cadena. strptime() analiza una cadena en un datetime. timedelta representa una duración que puedes sumar o restar.
from datetime import datetime, date, timedelta
now = datetime.now() # fecha y hora actual
today = date.today() # solo la fecha actual
print(now.year, now.month, now.day)
print(now.hour, now.minute, now.second)
# Formato
print(now.strftime("%Y-%m-%d")) # "2024-01-15"
print(now.strftime("%d %B %Y, %H:%M")) # "15 de enero de 2024, 09:42"
# Análisis
deadline = datetime.strptime("2024-12-31", "%Y-%m-%d")
# Aritmética
tomorrow = today + timedelta(days=1)
next_week = today + timedelta(weeks=1)
diff = deadline - now
print(f"{diff.days} días hasta la fecha límite")Códigos comunes de strftime:
| Código | Significado | Ejemplo |
|---|---|---|
%Y | Año de 4 dígitos | 2024 |
%m | Mes (con relleno de cero) | 01 |
%d | Día (con relleno de cero) | 15 |
%H | Hora (24h) | 09 |
%M | Minuto | 42 |
%B | Nombre completo del mes | enero |
datetime.now() te da la fecha y hora actuales. strftime() la convierte en una cadena con códigos como %Y-%m-%d, y strptime() va en la otra dirección, analizando una cadena nuevamente. timedelta es una duración que puedes sumar o restar, así que today + timedelta(days=1) es mañana. os y pathlib
pathlib es la forma moderna de trabajar con rutas de archivos. Los objetos Path te permiten construir, inspeccionar y navegar rutas usando el operador /. os da acceso a variables de entorno y operaciones de SO de nivel inferior. Prefiere pathlib para código nuevo.
from pathlib import Path
p = Path("data/reportes")
p.exists() # True si la ruta existe
p.is_dir() # True si es un directorio
p.is_file() # True si es un archivo
p.mkdir(parents=True, exist_ok=True) # crear directorios
for f in p.glob("*.csv"): # todos los archivos CSV en el directorio
print(f.name) # el nombre del archivo
report = p / "reporte_ene.csv" # operador / une rutas
report.stem # "reporte_ene" (nombre sin extensión)
report.suffix # ".csv"
report.parent # Path("data/reportes")
content = report.read_text() # leer contenidos del archivo directamente
report.write_text("nuevo contenido\n") # escribir directamentePara el módulo os:
import os
os.getcwd() # directorio de trabajo actual
os.listdir(".") # listar contenidos del directorio
os.path.exists("data.txt") # True si la ruta existe
os.path.join("data", "file.txt") # "data/file.txt" (multiplataforma)
os.environ.get("HOME") # leer una variable de entornoPrefiere pathlib para código nuevo. Usa os cuando necesites variables de entorno u trabajar con APIs más antiguas que esperan cadenas.
pathlib.Path trata una ruta de archivo como un objeto que puedes revisar: .exists(), .read_text(), .write_text(), .glob(). El operador `/` une piezas, así que p / "report.csv" se lee como una ruta real. Recurre a pathlib sobre el más antiguo os.path en código nuevo. timeit
timeit mide cuánto tiempo tarda el código en ejecutarse. Es útil cuando quieres comparar dos enfoques y elegir el más rápido. Ejecuta el código muchas veces para obtener una medición estable.
import timeit
# Cronometrar una única declaración
timeit.timeit("sum(range(1000))", number=10000)
# Cronometrar un bloque más complejo
setup = "data = list(range(1000))"
code = "[x * 2 for x in data]"
time = timeit.timeit(code, setup=setup, number=10000)
print(f"{time:.4f} segundos para 10,000 ejecuciones")number es cuántas veces repetir. Más repeticiones dan una medición más estable.
timeit.timeit() cronometra un pedazo de código ejecutándolo una y otra vez, luego divides por el conteo de ejecución para un número estable por llamada. Es cómo resuelves "cuál de estos dos es más rápido" en lugar de adivinar. Una ejecución es demasiado ruidosa para confiar, así que deja que haga un bucle. string
El módulo string proporciona constantes de cadena preformadas para letras, dígitos y puntuación. Útil cuando necesitas verificar caracteres o generar cadenas aleatorias a partir de un alfabeto específico.
import string
string.ascii_lowercase # "abcdefghijklmnopqrstuvwxyz"
string.ascii_uppercase # "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
string.ascii_letters # ambos combinados
string.digits # "0123456789"
string.punctuation # todos los caracteres de puntuaciónÚtil cuando necesitas verificar caracteres o generar cadenas aleatorias:
import string, random
chars = string.ascii_letters + string.digits
password = "".join(random.choices(chars, k=12))string te entrega conjuntos de caracteres preformados: string.ascii_letters, string.digits, string.punctuation. Son cadenas simples, así que puedes hacer bucles sobre ellas o muestrear de ellas. Práctico siempre que necesites un alfabeto conocido para construir o verificar. Crear tus propios módulos
Cualquier archivo de Python es un módulo. Para usarlo desde otro archivo, impórtalo por el nombre del archivo (sin .py). Puedes importar el módulo completo y usar su contenido con notación de punto, o importar nombres específicos directamente.
# utils.py
def clamp(value, lo, hi):
return max(lo, min(value, hi))
PI = 3.14159# main.py
import utils
utils.clamp(150, 0, 100) # 100
utils.PI # 3.14159
from utils import clamp
clamp(50, 0, 100) # 50Python encuentra el módulo buscando en el mismo directorio que el archivo de importación (y algunos otros lugares). Para proyectos más grandes, los módulos se organizan en paquetes: directorios con un archivo __init__.py.
.py es ya un módulo: impórtalo por su nombre de archivo sin .py, y sus funciones y variables son tuyas para usar. import utils luego utils.clamp(...), o extrae un nombre con from utils import clamp. Así es cómo divides un programa en crecimiento entre archivos. __name__ == "__main__"
Cuando Python ejecuta un archivo directamente, __name__ se establece en "__main__". Cuando el mismo archivo se importa como un módulo, __name__ es el nombre del módulo. Este patrón te permite escribir código que se ejecuta cuando ejecutas el archivo directamente pero se omite cuando el archivo es importado por otro módulo.
# utils.py
def clamp(value, lo, hi):
return max(lo, min(value, hi))
if __name__ == "__main__":
# esto solo se ejecuta cuando haces: python utils.py
# no cuando haces: import utils
print(clamp(150, 0, 100)) # 100Este es un patrón estándar para cualquier módulo que también es útil como script independiente.
if __name__ == "__main__": permite que un archivo sea tanto un módulo importable como un script ejecutable. El código bajo la guardia se ejecuta cuando haces python utils.py, y se omite cuando otro archivo hace import utils. Práctico para esconder una demostración o prueba rápida al final de un módulo. Aspectos destacados de la biblioteca estándar
Algunos módulos más que vale la pena conocer. Cada uno resuelve un problema común que llevaría un trabajo significativo implementar por ti mismo.
collections: tipos de contenedor especializados:
from collections import Counter, defaultdict, deque
Counter(["a", "b", "a", "c", "a"]) # Counter({'a': 3, 'b': 1, 'c': 1})
defaultdict(list) # dict que auto-crea claves faltantes
deque([1, 2, 3], maxlen=5) # append/pop rápido de ambos extremositertools: herramientas para trabajar con iterables:
import itertools
list(itertools.chain([1, 2], [3, 4])) # [1, 2, 3, 4]
list(itertools.islice(range(100), 5)) # [0, 1, 2, 3, 4]
list(itertools.combinations([1, 2, 3], 2)) # [(1, 2), (1, 3), (2, 3)]
list(itertools.product([0, 1], repeat=2)) # [(0,0), (0,1), (1,0), (1,1)]sys: acceso al intérprete de Python:
import sys
sys.argv # lista de argumentos de línea de comandos
sys.exit(1) # salir con un código de estado
sys.version # cadena de versión de PythonPaquetes de terceros: más allá de la biblioteca estándar, pip instala paquetes de la comunidad:
pip install requests # biblioteca HTTP
pip install pandas # manipulación de datos
pip install numpy # computación numéricaLos paquetes de terceros están fuera del alcance de esta guía, pero el patrón es siempre el mismo: pip install, luego import.
En la práctica
Combinando random, string, y datetime para generar IDs de juego únicos con marcas de tiempo:
import random
import string
from datetime import datetime
def generate_game_id(length: int = 8) -> str:
chars = string.ascii_uppercase + string.digits
return "".join(random.choices(chars, k=length))
def timestamp() -> str:
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
game_id = generate_game_id()
print(f"[{timestamp()}] Iniciando juego {game_id}")
scores = [random.randint(50, 100) for _ in range(5)]
print(f"Puntuaciones de la ronda: {scores}")
print(f"Mejor: {max(scores)}")
