# Módulos y paquetes de Python: import, pip, venv y bibliotecas explicados con sencillez

URL: https://skillaria.top/es/guides/python/modulos-python

Un módulo en Python es un archivo .py, un paquete es una carpeta de módulos y una biblioteca es un conjunto de paquetes que se incorpora con import. Las bibliotecas de terceros se instalan con pip (o uv) dentro de un entorno virtual venv, una carpeta aislada con su propio intérprete y sus paquetes, para que las versiones de distintos proyectos no entren en conflicto.

Un módulo en Python es un archivo normal con código, y `import` es la forma de tomar de él funciones y clases. Con los módulos se forman los paquetes, con los paquetes se forman las bibliotecas, y para que las bibliotecas de terceros de distintos proyectos no se estorben entre sí se instalan en un entorno virtual venv. Vamos a repasar toda la cadena: qué ocurre al importar, cómo está organizado un paquete, cómo funcionan pip y venv en Python y qué son los imports perezosos que llegaron en Python 3.15.

## Módulo, paquete, biblioteca: en qué se diferencian

| Concepto | Qué es | Ejemplo |
| --- | --- | --- |

| Módulo | Un único archivo `.py`; el nombre del módulo es el nombre del archivo sin extensión | `categorias.py` → `import categorias` |

| Paquete | Una carpeta con módulos y un archivo `__init__.py` | `gastos/informe.py` → `from gastos.informe import construir` |

| Biblioteca | Un conjunto listo de módulos y paquetes para una tarea | `requests`, `pandas`, la estándar `pathlib` |

| Distribución (paquete de PyPI) | Un archivo que instala pip | `pip install requests` |

En la conversación, «biblioteca», «paquete» y «módulo» se mezclan a menudo; no pasa nada. Lo importante es que, técnicamente, `import` carga siempre un módulo o un paquete, y pip instala una distribución de PyPI, dentro de la cual hay paquetes.

## Cómo funciona import en Python

Hay varias formas de importar, y todas aparecen en código real:

```
import math                    # el módulo completo, uso math.sqrt
from math import sqrt, pi      # nombres concretos
import datetime as dt          # alias
from collections import Counter as C

print(math.sqrt(16), sqrt(9), pi)
print(dt.date.today())
```

Los alias son habituales en las bibliotecas grandes: `import numpy as np`, `import pandas as pd`. La construcción `from modulo import *` conviene evitarla: llena el espacio de nombres y oculta de dónde viene cada nombre.

### Qué hace import realmente

1. Busca el módulo en la caché `sys.modules`. Si ya está cargado, simplemente lo devuelve.
2. Si no está, busca el archivo en las carpetas de `sys.path`: la carpeta del script que se ejecuta, la biblioteca estándar, el site-packages del entorno.
3. Ejecuta el archivo encontrado completo, de arriba abajo.
4. Guarda el objeto del módulo en la caché y lo asocia al nombre.

De aquí se derivan dos conclusiones prácticas. Volver a importar el mismo módulo es casi gratis: el código no se vuelve a ejecutar. Y todo el código de nivel superior del módulo, incluidos los `print` y los cálculos pesados, se ejecuta al importarlo.

```
import sys
for p in sys.path:
    print(p)
print("math" in sys.modules)
```

### if __name__ == "__main__"

Como importar ejecuta el archivo, hace falta una forma de distinguir «me han ejecutado como script» de «me han importado». Para eso existe la variable `__name__`: al ejecutar el archivo vale `"__main__"`, y al importarlo, el nombre del módulo.

```
# categorias.py
def adivinar(titulo: str) -> str:
    return "comida" if "café" in titulo.lower() else "otros"

if __name__ == "__main__":
    print(adivinar("Café de casa"))   # se ejecuta solo con python categorias.py
```

Para un paquete existe una alternativa: un archivo `__main__.py` dentro y el arranque con `python -m gastos`.

## Módulos estándar de Python

Python viene «con pilas incluidas»: cientos de módulos integrados están disponibles sin instalar nada. Los más usados:

| Módulo | Para qué sirve |
| --- | --- |

| `os`, `sys`, `pathlib`, `shutil` | Sistema, rutas y archivos |

| `json`, `csv`, `pickle` | Formatos de datos |

| `datetime`, `time`, `calendar` | Fecha y hora |

| `math`, `random`, `statistics`, `fractions` | Números |

| `re`, `string` | Trabajo con texto |

| `collections`, `itertools`, `functools` | Estructuras de datos e iteradores |

| `logging`, `argparse`, `subprocess` | Registros, argumentos de línea de comandos, ejecución de programas |

| `asyncio`, `threading` | Asincronía e hilos |

La lista completa de módulos de la biblioteca estándar está en `sys.stdlib_module_names` (Python 3.10 o superior). Para ver qué contiene un módulo se usan `dir(math)` y `help(math)`.

## Paquete propio: estructura del proyecto

Cuando hay muchos módulos, se agrupan en un paquete. Una disposición habitual es el src-layout:

```
gastos-proyecto/
├── pyproject.toml
└── src/
    └── gastos/
        ├── __init__.py
        ├── cli.py
        ├── analisis.py
        ├── categorias.py
        └── informe.py
```

Dentro del paquete, los módulos se importan entre sí por el nombre del paquete (`from gastos.categorias import adivinar`) o de forma relativa (`from .categorias import adivinar`). La importación relativa solo funciona dentro del paquete, no en un archivo ejecutado directamente como script.

## pip en Python: instalar bibliotecas

Las bibliotecas de terceros están en el catálogo PyPI, y las instala la utilidad pip, que viene con Python. Lo más seguro es invocarla a través del intérprete: así la biblioteca acaba exactamente en el Python con el que ejecuta su código.

```
python -m pip install requests          # instalar
python -m pip install "pandas>=2.3"     # con restricción de versión
python -m pip install --upgrade requests
python -m pip uninstall requests        # desinstalar
python -m pip list                      # lista de paquetes instalados
python -m pip show requests             # versión y dependencias
python -m pip freeze > requirements.txt
python -m pip install -r requirements.txt
```

En Windows, en lugar de `python` se suele usar el lanzador `py`. Si pip no se encuentra, lo instala el módulo integrado: `python -m ensurepip --upgrade`.

### Bibliotecas populares de Python

En PyPI hay cientos de miles de paquetes, pero en la mayoría de los proyectos aparece siempre la misma lista corta. Conviene empezar por ella, en lugar de buscar exotismos.

| Tarea | Bibliotecas |
| --- | --- |

| Peticiones HTTP y APIs | `requests`, `httpx` |

| Análisis de datos y tablas | `pandas`, `numpy` |

| Gráficos | `matplotlib` |

| Servicios web | `fastapi`, `django`, `flask` |

| Pruebas | `pytest` |

| Imágenes | `pillow` (se importa como `PIL`) |

Ojo: el nombre para instalar y el nombre para importar no siempre coinciden. Se instala `pip install pillow`, pero se escribe `from PIL import Image`; se instala `opencv-python`, pero se importa `cv2`. Si `import` falla justo después de instalar, compruebe en la documentación del paquete con qué nombre se importa.

### Instalar bibliotecas en Linux

En las versiones recientes de Debian y Ubuntu, el comando `pip install` en el Python del sistema termina con el error `externally-managed-environment` (PEP 668). Es una protección: el Python del sistema pertenece al gestor de paquetes del sistema operativo, y pip no debe romperlo. La solución correcta no es `--break-system-packages`, sino un entorno virtual.

## venv en Python: entorno virtual

Un entorno virtual es una carpeta independiente con su propia copia del intérprete (un enlace a él) y su propio site-packages. Las bibliotecas instaladas en él solo son visibles para ese proyecto. Así, un proyecto puede usar Django 4 y otro, Django 5, sin conflictos.

El módulo `venv` viene integrado en Python y no hace falta instalarlo aparte (en Debian/Ubuntu a veces se necesita el paquete del sistema `python3-venv`).

```
# crear el entorno en la carpeta .venv
python -m venv .venv

# activar: Linux y macOS
source .venv/bin/activate
# activar: Windows PowerShell
.venv\Scripts\Activate.ps1

# ahora pip instala los paquetes dentro de .venv
python -m pip install requests
python -c "import sys; print(sys.prefix)"

# salir del entorno
deactivate
```

Tras activar el entorno, al principio de la línea del terminal aparece `(.venv)`. La carpeta del entorno no se sube a git (añada `.venv/` a `.gitignore`) ni se traslada entre equipos: en su lugar se guarda la lista de dependencias y el entorno se vuelve a crear. Si PowerShell impide ejecutar el script de activación, permítalo para el usuario con `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned`.

### uv y pyproject.toml

Los proyectos modernos describen sus dependencias en `pyproject.toml`. El gestor uv, que usamos en el curso, combina la creación del entorno y la instalación: `uv add pandas` descarga el paquete, lo añade a `pyproject.toml` y fija las versiones exactas en `uv.lock`. Un compañero clona el proyecto, ejecuta `uv sync` y obtiene exactamente el mismo entorno.

```
[project]
name = "gastos"
version = "0.1.0"
requires-python = ">=3.15"
dependencies = [
    "pandas>=2.3",
]

[project.scripts]
gastos = "gastos.cli:main"
```

## Imports perezosos en Python 3.15 (PEP 810)

La novedad principal de la versión 3.15 en este tema es la palabra clave `lazy`. Las bibliotecas pesadas tardan en cargarse: en la medición del curso, con la imagen `python:3.15-slim`, un `import pandas` normal tardó unos 415 ms, y `lazy import pandas`, unos 13 ms. Para una utilidad de línea de comandos que se lanza para ver `--help`, la diferencia es enorme.

```
lazy import pandas as pd
lazy from gastos.informe import construir_informe

def main() -> None:
    ...
    df = pd.read_csv(ruta)   # aquí se carga pandas de verdad
```

En lugar del módulo, el nombre recibe un objeto proxy (`types.LazyImportType`), y la importación real se hace en el primer uso del nombre. Si ese uso nunca llega, no se pierde tiempo en absoluto.

### Limitaciones de lazy import

- Solo se permite en el nivel superior del módulo: dentro de una función, una clase o un `try/except` produce `SyntaxError`.
- `lazy from x import *` está prohibido.
- `ModuleNotFoundError` aparece no al arrancar, sino en el primer uso.
- Los efectos secundarios del módulo (registro de complementos, etc.) se desplazan en el tiempo.

Para hacer perezosos todos los imports a la vez se usa el indicador `-X lazy_imports=all` o la variable `PYTHON_LAZY_IMPORTS=all`, y las excepciones se definen con `sys.set_lazy_imports_filter()`. Para un código que debe funcionar también en versiones antiguas existe la variable del módulo `__lazy_modules__ = ["pandas"]`: Python 3.15 hará perezosos los imports indicados, y las versiones antiguas simplemente ejecutarán un `import` normal. Para ver dónde se gasta el tiempo al arrancar, sirve `python -X importtime -c "import pandas"`. Se benefician sobre todo los programas que se lanzan a menudo y durante poco tiempo; un servidor de larga duración apenas gana nada con la carga perezosa.

## Errores típicos

- `ModuleNotFoundError: No module named 'requests'`: la biblioteca se instaló en otro Python o el entorno no está activado. Compruebe con `python -m pip show requests` usando el mismo intérprete.
- Un archivo propio se llama `json.py`, `random.py` o `csv.py`: la carpeta del script ocupa el primer lugar en `sys.path` y tapa el módulo estándar. Python 3.13 y superiores sugieren «consider renaming» en el error. Cambie el nombre del archivo y borre `__pycache__`.
- Importación circular: `a.py` importa `b.py`, y este, a `a.py`. Saque lo común a un tercer módulo o importe dentro de una función.
- Ejecutar pip dentro del intérprete (`>>> pip install`) produce `SyntaxError`. Los comandos de pip se ejecutan en la terminal.

## Resumen

El módulo es un archivo, el paquete es una carpeta de módulos y la biblioteca es su conjunto listo; `import` busca el módulo en la caché y en `sys.path`, y lo ejecuta una sola vez. Instale las bibliotecas de terceros con pip o uv solo dentro de un entorno virtual venv: así los proyectos no se estorban y el entorno se puede reproducir fácilmente. En el curso de Python este tema se practica convirtiendo el registro de gastos en un paquete con dependencias y un arranque rápido gracias a los imports perezosos.

## FAQ

**¿Hay que crear un venv para cada proyecto?**

Sí, es una buena práctica: cada proyecto tiene sus propias versiones de las bibliotecas, y un entorno aparte evita conflictos y no ensucia el Python del sistema.

**¿En qué se diferencia pip de uv?**

pip solo instala paquetes; uv además crea el entorno, anota las dependencias en pyproject.toml y fija las versiones exactas en un archivo de bloqueo. Además, es bastante más rápido.

**¿Cómo ver la lista de bibliotecas instaladas en Python?**

Ejecute python -m pip list en el entorno correspondiente; pip freeze muestra la misma lista en el formato de requirements.txt.

**¿Dónde se guardan los módulos instalados?**

En la carpeta site-packages del entorno actual. La ruta de un módulo concreto la indica su atributo __file__: por ejemplo, import requests; print(requests.__file__).

**¿Se puede copiar la carpeta venv a otro ordenador?**

No: el entorno está ligado a las rutas y al intérprete de la máquina. Lo que se traslada es la lista de dependencias, y el entorno se crea de nuevo.


---
Source: Skillaria.Top (https://skillaria.top)
