Módulos y paquetes en Python: import, stdlib, pip y entornos virtuales

📅 Actualizado en marzo 2026 📊 Nivel: Principiante ⏱️ 16 min de lectura

Python tiene fama de venir con las pilas incluidas. No es un eslogan vacío: la biblioteca estándar incluye más de 200 módulos que resuelven desde operaciones matemáticas hasta servidores HTTP, pasando por compresión de archivos, generación de contraseñas seguras y análisis de fechas. Y cuando la stdlib no es suficiente, PyPI tiene más de 500.000 paquetes a un pip install de distancia.

Saber importar bien, organizar el propio código en módulos y gestionar dependencias con entornos virtuales es lo que distingue un script de un proyecto real.

📥 import: las cinco formas de importar

# 1. Importar el módulo completo (acceso con prefijo)
import math
math.sqrt(16)      # 4.0
math.pi            # 3.141592...

# 2. Importar nombres específicos (sin prefijo)
from math import sqrt, pi, ceil
sqrt(25)           # 5.0

# 3. Alias — nombre corto por convención
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
np.array([1, 2, 3])

# 4. Importar subpaquete
import os.path
os.path.exists("config.json")

from pathlib import Path    # más común
Path("config.json").exists()

# 5. Importar todo — evitar siempre
from os import *    # ⚠ contamina el namespace local

# Cuándo usar cada forma:
# import módulo     → cuando usas pocas cosas del módulo
# from módulo import X → cuando usas X muchas veces
# import módulo as m   → convención de terceros (numpy, pandas...)
Mapa conceptual del sistema de módulos de Python: stdlib, paquetes de terceros, módulos propios, formas de importar y estructura de paquete
El ecosistema de módulos de Python: tu script en el centro recibe código de la stdlib (verde, sin instalar), de terceros vía pip (naranja), y de tus propios archivos .py (morado). Abajo, las formas de importar y la estructura de un paquete. Infografía: Ciberaula.

📚 Biblioteca estándar: los módulos que más usarás

## os — sistema operativo
import os
os.getcwd()                    # directorio actual
os.listdir(".")                # listar archivos
os.environ.get("HOME")         # variables de entorno
os.path.join("data", "f.csv")  # unir rutas (mejor pathlib)

## datetime — fechas y horas
from datetime import datetime, date, timedelta
hoy = date.today()
ahora = datetime.now()
manana = hoy + timedelta(days=1)
ahora.strftime("%d/%m/%Y %H:%M")    # "06/03/2026 14:30"
datetime.strptime("2026-03-06", "%Y-%m-%d")  # parse

## random — aleatoriedad
import random
random.randint(1, 10)           # entero entre 1 y 10
random.choice(["a", "b", "c"]) # elemento aleatorio
random.shuffle(lista)           # mezclar in-place
random.sample(lista, 3)         # 3 elementos sin repetir
random.seed(42)                 # reproducibilidad

## collections — estructuras avanzadas
from collections import Counter, defaultdict, deque, namedtuple
Counter("banana")               # Counter({'a':3,'n':2,'b':1})
d = defaultdict(list)           # sin KeyError al añadir
d["clave"].append(1)
cola = deque([1,2,3], maxlen=3) # cola de tamaño fijo
Punto = namedtuple("Punto", ["x","y"])
p = Punto(10, 20); p.x          # 10

## logging — logs profesionales
import logging
logging.basicConfig(level=logging.INFO,
    format="%(asctime)s %(levelname)s %(message)s")
logging.info("Aplicación iniciada")
logging.warning("Disco casi lleno")
logging.error("Conexión fallida")
Pasillo de supermercado con estanterías llenas de productos y carrito de compra en primer plano
PyPI es el supermercado de Python: más de 500.000 paquetes en las estanterías. Con pip install metes en el carrito exactamente lo que necesitas para tu proyecto. Fuente: Pexels (licencia libre).

🧩 Crear tus propios módulos

Cualquier archivo .py es un módulo importable. Dividir el código en módulos hace que sea más fácil leer, reutilizar y probar.

# ── archivo: utils.py ──────────────────────────────
"""Utilidades de formato para la aplicación."""

IVA = 0.21    # constante del módulo

def precio_con_iva(precio_base):
    """Devuelve el precio final aplicando IVA."""
    return round(precio_base * (1 + IVA), 2)

def formatear_euros(cantidad):
    """Formatea una cantidad como string en euros."""
    return f"{cantidad:,.2f} €".replace(",", ".")

def es_email_valido(email):
    """Comprobación básica de formato de email."""
    return "@" in email and "." in email.split("@")[-1]


# ── archivo: main.py ───────────────────────────────
import utils

precio = utils.precio_con_iva(100)
print(utils.formatear_euros(precio))   # "121,00 €"

# O importando nombres directamente:
from utils import precio_con_iva, formatear_euros

print(formatear_euros(precio_con_iva(250)))   # "302,50 €"
💡 if __name__ == "__main__": Añade este bloque al final de tus módulos para poder ejecutarlos directamente como scripts y importarlos como módulos sin que el código de prueba se ejecute al importar.
# utils.py con bloque de prueba protegido
def precio_con_iva(precio_base):
    return round(precio_base * 1.21, 2)

if __name__ == "__main__":
    # Este bloque SOLO se ejecuta con: python utils.py
    # NO se ejecuta cuando haces: import utils
    print(precio_con_iva(100))   # 121.0
    print(precio_con_iva(250))   # 302.5

📦 Paquetes: módulos organizados en carpetas

# Estructura de un proyecto bien organizado:
# mi_app/
# ├── main.py
# ├── requirements.txt
# └── mi_app/
#     ├── __init__.py       ← hace de esta carpeta un paquete
#     ├── config.py
#     ├── modelos.py
#     └── utils/
#         ├── __init__.py
#         ├── formato.py
#         └── validacion.py

# __init__.py puede estar vacío o definir qué se exporta:
# mi_app/__init__.py
from .config import Config
from .modelos import Usuario, Producto

# Importar desde el paquete:
from mi_app import Config
from mi_app.utils.formato import formatear_euros
from mi_app.utils import validacion

# Importación relativa (dentro del paquete):
# en modelos.py:
from .config import Config       # mismo nivel
from ..utils.formato import f    # nivel superior

⚙️ pip: instalar paquetes de terceros

# En la terminal (no en el script Python):

# Instalar
pip install requests
pip install requests==2.31.0          # versión exacta
pip install "requests>=2.28,<3.0"     # rango de versiones
pip install -r requirements.txt        # desde lista

# Información
pip list                               # paquetes instalados
pip show requests                      # detalles de un paquete
pip search término                     # buscar (desactivado, usar pypi.org)

# Actualizar / desinstalar
pip install --upgrade requests
pip uninstall requests

# Guardar dependencias del proyecto
pip freeze > requirements.txt          # snapshot exacto
Mecánico trabajando bajo el capó de un coche en un taller con herramientas y estanterías al fondo
Un mecánico combina piezas estándar con piezas de recambio para hacer funcionar el motor. En Python, combinas stdlib, paquetes de terceros y código propio para construir tu aplicación. Fuente: Pexels (licencia libre).

🧪 Entornos virtuales con venv

Sin entorno virtual, todos tus proyectos comparten los mismos paquetes instalados globalmente. Si dos proyectos necesitan versiones distintas del mismo paquete, hay conflicto. venv crea un espacio aislado por proyecto.

# En la terminal:

# 1. Crear el entorno virtual
python -m venv venv          # crea carpeta "venv/"
python -m venv .venv         # convención: carpeta oculta

# 2. Activar
source venv/bin/activate     # Unix / macOS
venv\Scripts\activate        # Windows (cmd)
venv\Scripts\Activate.ps1    # Windows (PowerShell)

# El prompt cambia a: (venv) usuario@máquina:~/proyecto$

# 3. Instalar paquetes (solo en este entorno)
pip install requests flask pandas

# 4. Guardar dependencias
pip freeze > requirements.txt

# 5. Desactivar cuando termines
deactivate

# Recrear el entorno en otra máquina:
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
Referencia rápida de módulos Python: stdlib esencial, formas de importar y comandos pip y venv
Referencia rápida — Stdlib esencial (18 módulos más usados), las cinco formas de importar con cuándo usar cada una, y todos los comandos de pip y venv para gestionar dependencias. Ficha: Ciberaula.

🛠️ Programa completo: proyecto bien estructurado

# Estructura del proyecto:
# conversor/
# ├── main.py
# ├── requirements.txt       (vacío — solo stdlib)
# └── conversor/
#     ├── __init__.py
#     ├── divisas.py
#     ├── temperaturas.py
#     └── utils.py

# ── conversor/utils.py ──────────────────────────
"""Utilidades compartidas."""
import logging
from datetime import datetime

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    datefmt="%H:%M:%S"
)
logger = logging.getLogger(__name__)

def redondear(valor, decimales=2):
    return round(valor, decimales)

def timestamp():
    return datetime.now().strftime("%H:%M:%S")


# ── conversor/temperaturas.py ───────────────────
"""Conversiones de temperatura."""
from .utils import redondear, logger

def celsius_a_fahrenheit(c):
    resultado = redondear(c * 9/5 + 32)
    logger.info(f"{c}°C → {resultado}°F")
    return resultado

def fahrenheit_a_celsius(f):
    resultado = redondear((f - 32) * 5/9)
    logger.info(f"{f}°F → {resultado}°C")
    return resultado

def celsius_a_kelvin(c):
    return redondear(c + 273.15)


# ── conversor/divisas.py ────────────────────────
"""Conversiones de divisas (tasas de ejemplo)."""
from .utils import redondear, logger

TASAS = {
    ("EUR", "USD"): 1.08,
    ("USD", "EUR"): 0.93,
    ("EUR", "GBP"): 0.85,
    ("GBP", "EUR"): 1.18,
}

def convertir(cantidad, origen, destino):
    clave = (origen.upper(), destino.upper())
    if clave not in TASAS:
        raise ValueError(f"Par no disponible: {origen}/{destino}")
    resultado = redondear(cantidad * TASAS[clave])
    logger.info(f"{cantidad} {origen} → {resultado} {destino}")
    return resultado


# ── main.py ─────────────────────────────────────
from conversor.temperaturas import celsius_a_fahrenheit, fahrenheit_a_celsius
from conversor.divisas import convertir

def menu():
    while True:
        print("\n=== CONVERSOR ===")
        print("1. Temperatura  2. Divisas  3. Salir")
        op = input("Opción: ").strip()

        if op == "1":
            valor = float(input("Celsius: "))
            print(f"  → {celsius_a_fahrenheit(valor)} °F")
        elif op == "2":
            cant = float(input("Cantidad: "))
            orig = input("De (ej. EUR): ").strip()
            dest = input("A (ej. USD): ").strip()
            try:
                print(f"  → {convertir(cant, orig, dest)} {dest}")
            except ValueError as e:
                print(f"  Error: {e}")
        elif op == "3":
            break

if __name__ == "__main__":
    menu()

🐛 Errores clásicos con módulos

1. Archivo con el mismo nombre que un módulo de stdlib

# ❌ Si tienes un archivo llamado random.py en tu proyecto:
import random        # importa TU random.py, no la stdlib
random.randint(1,10) # AttributeError: sin randint

# ✅ Renombra tu archivo: mi_random.py, generador.py...
# Para verificar qué se está importando:
import random; print(random.__file__)

2. Instalar paquete globalmente cuando deberías usar venv

# ❌ Sin activar el entorno virtual:
pip install flask       # se instala globalmente

# ✅ Siempre con el entorno activado:
source venv/bin/activate
pip install flask       # solo en este proyecto

3. ImportError por olvidar __init__.py (Python < 3.3)

# Si tu paquete no tiene __init__.py en Python 2 o entornos legacy:
# ImportError: No module named 'mi_paquete'

# ✅ Crear __init__.py (puede estar vacío):
# mi_paquete/__init__.py   ← aunque esté vacío, es necesario

4. Importación circular

# ❌ a.py importa b.py, b.py importa a.py → ImportError circular
# a.py: from b import funcion_b
# b.py: from a import funcion_a    ← círculo

# ✅ Soluciones:
# - Mover el código compartido a un tercer módulo (utils.py)
# - Importar dentro de la función, no a nivel de módulo
# - Reorganizar las dependencias

✅ Resumen y próximos pasos

Los módulos son la unidad de reutilización de Python. La stdlib resuelve el 80% de los problemas sin instalar nada. Para el resto, pip descarga paquetes de PyPI. Los entornos virtuales aíslan las dependencias por proyecto — siempre uno por proyecto. Y dividir el código propio en módulos y paquetes hace que escale sin convertirse en un monolito inmanejable.

La siguiente lección: Programación orientada a objetos — clases, objetos, atributos, métodos y herencia. El salto a Módulo 4.

❓ Preguntas frecuentes

❓ Preguntas frecuentes sobre Módulos y paquetes en Python: import, stdlib, pip y entornos virtuales

Las dudas más comunes respondidas de forma clara y directa.

Un módulo es un único archivo .py. Un paquete es una carpeta que contiene varios módulos y un archivo __init__.py que le dice a Python "esto es un paquete". La distinción es principalmente organizativa: cuando tienes muchos módulos relacionados, los agrupas en un paquete. Por ejemplo, pathlib es un módulo (pathlib.py dentro de la stdlib), mientras que email es un paquete (carpeta con varios módulos para diferentes partes del protocolo).
Para scripts cortos y de un solo uso, no es imprescindible. Pero en cuanto tengas un proyecto real, sí. Sin entornos virtuales, todos los proyectos comparten los mismos paquetes instalados globalmente. Si el proyecto A necesita requests 2.28 y el proyecto B necesita requests 2.31, hay conflicto. El entorno virtual da a cada proyecto su propio espacio aislado. El coste es mínimo (unos segundos crearlos) y el beneficio es enorme.
En Python 3.3+ ya no es estrictamente obligatorio gracias a los "namespace packages". Pero sigue siendo una buena práctica incluirlo porque hace el comportamiento explícito, permite ejecutar código al importar el paquete, y define qué se exporta cuando alguien hace from mi_paquete import *. Para la mayoría de proyectos, un __init__.py vacío es suficiente para marcar la carpeta como paquete.
El problema más habitual es tener un archivo propio con el mismo nombre que un módulo de stdlib o de terceros. Por ejemplo, si creas random.py en tu proyecto, import random cargará el tuyo en lugar del de la stdlib. La solución es nunca nombrar tus archivos como módulos conocidos. Para verificar qué módulo se está importando: import random; print(random.__file__).
No, nunca. El entorno virtual ocupa espacio, contiene binarios específicos del sistema operativo y puede regenerarse en cualquier máquina con pip install -r requirements.txt. Añade venv/ (o .venv/) a tu .gitignore. Lo que sí debes incluir en el repositorio es el archivo requirements.txt generado con pip freeze > requirements.txt, que es la receta para recrear el entorno.
Cuando Python ejecuta un archivo directamente (python mi_script.py), la variable __name__ vale "__main__". Cuando ese mismo archivo es importado como módulo desde otro archivo, __name__ vale el nombre del módulo ("mi_script"). El bloque if __name__ == "__main__" permite que un archivo funcione tanto como script ejecutable como módulo importable, ejecutando la lógica principal solo cuando se llama directamente.
Valora este artículo

💬 Foro de discusión

¿Tienes dudas sobre Módulos y paquetes en Python: import, stdlib, pip y entornos virtuales? Comparte tu pregunta con la comunidad.

¿Tienes cuenta? o comenta como invitado ↓

Todavía no hay mensajes. ¡Sé el primero en participar!