Entornos virtuales y dependencias

Un proyecto, un entorno: la regla que acaba con los conflictos de versiones.

Duración: ~30 minutosHerramientas: ShellAntes, conviene haber hecho: «Tu puesto de trabajo de IA, desde cero»

Qué vas a aprender

  • Crear entornos virtuales aislados con uv, venv o conda
  • Escribir un pyproject.toml con grupos de dependencias opcionales y generar lockfiles reproducibles
  • Diagnosticar y corregir los errores típicos: instalaciones globales, mezclar pip y conda, versiones de CUDA incompatibles
  • Aplicar una estrategia de un entorno por módulo en proyectos con dependencias en conflicto

Por qué importa

Instalas PyTorch 2.4 para un proyecto de fine-tuning. La semana siguiente, otro proyecto necesita PyTorch 2.1 porque su compilación de CUDA está fijada. Actualizas de forma global y el primer proyecto se rompe. Vuelves atrás y se rompe el segundo.

Esto es el infierno de las dependencias, y en IA pasa constantemente porque:

  • PyTorch, JAX y TensorFlow traen cada uno sus propios enlaces con CUDA
  • Las librerías de modelos fijan versiones concretas del framework
  • Un pip install global sobrescribe lo que hubiera antes
  • Las compilaciones para CUDA 11.8 no funcionan con drivers de CUDA 12.x (y viceversa)

La solución: cada proyecto tiene su propio entorno aislado, con sus propios paquetes.

La idea clave

graph TD
    subgraph sin["Sin entornos virtuales"]
        SP[Python del sistema] --> T24["torch 2.4.0 (CUDA 12.4)\nlo necesita el proyecto A"]
        SP --> T21["torch 2.1.0 (CUDA 11.8)\nlo necesita el proyecto B"]
        SP --> CONFLICT["CONFLICTO: solo puede\nexistir una versión de torch"]
    end

    subgraph con["Con entornos virtuales"]
        PA["Proyecto A (.venv/)"] --> PA1["torch 2.4.0 (CUDA 12.4)"]
        PA --> PA2["transformers 4.44"]
        PB["Proyecto B (.venv/)"] --> PB1["torch 2.1.0 (CUDA 11.8)"]
        PB --> PB2["diffusers 0.28"]
    end

Paso a paso

Opción 1: uv venv (recomendada)

uv es el gestor de paquetes de Python más rápido (de 10 a 100 veces más que pip). Gestiona entornos virtuales, versiones de Python y resolución de dependencias con una sola herramienta.

curl -LsSf https://astral.sh/uv/install.sh | sh

uv python install 3.12

cd tu-proyecto
uv venv
source .venv/bin/activate

Instala paquetes:

uv pip install torch numpy

Crea un proyecto con pyproject.toml en un solo paso:

uv init mi-proyecto-ia
cd mi-proyecto-ia
uv add torch numpy matplotlib

Opción 2: venv (incluido en Python)

Si no puedes instalar uv, Python trae venv:

python3 -m venv .venv
source .venv/bin/activate  # Linux/macOS
.venv\Scripts\activate     # Windows

pip install torch numpy

Es más lento que uv, pero funciona en cualquier sitio donde haya Python.

Opción 3: conda (cuando de verdad la necesitas)

Conda gestiona dependencias que no son de Python, como el toolkit de CUDA, cuDNN o librerías de C. Úsala cuando:

  • Necesites una versión concreta del toolkit de CUDA sin instalarla en todo el sistema
  • Trabajes en un clúster compartido donde no puedes instalar paquetes del sistema
  • Las instrucciones de instalación de una librería digan «usa conda»
# Instala miniconda (no el Anaconda completo)
curl -LsSf https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -o miniconda.sh
bash miniconda.sh -b

conda create -n miproyecto python=3.12
conda activate miproyecto

conda install pytorch torchvision torchaudio pytorch-cuda=12.4 -c pytorch -c nvidia

Una regla: si usas conda para un entorno, usa conda para todos los paquetes de ese entorno. Mezclar pip install dentro de un entorno de conda provoca conflictos de dependencias muy difíciles de depurar.

Para este curso: un entorno por módulo

Podrías crear un único entorno para todo el curso. No lo hagas: módulos distintos necesitan dependencias distintas (y a veces incompatibles).

Estrategia:

mi-curso-ia/
├── .venv/                    <-- entorno ligero compartido para los módulos 0-3
├── 04-deep-learning/
│   └── .venv/                <-- entorno con PyTorch
├── 24-vision/
│   └── .venv/                <-- el mismo entorno de PyTorch (enlazado o compartido)
├── 07-transformers/
│   └── .venv/                <-- puede necesitar otras versiones de transformers
└── 12-aplicaciones-llm/
    └── .venv/                <-- SDKs de APIs, sin torch

El script preparar_entorno.sh (en «Archivos de la lección») crea el entorno base del curso en la carpeta donde lo ejecutes.

Lo básico de pyproject.toml

Todo proyecto de Python debería tener un pyproject.toml. Sustituye a setup.py, setup.cfg y requirements.txt en un único archivo.

[project]
name = "mi-curso-ia"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
    "numpy>=1.26",
    "matplotlib>=3.8",
    "jupyter>=1.0",
    "scikit-learn>=1.4",
]

[project.optional-dependencies]
torch = ["torch>=2.3", "torchvision>=0.18"]
llm = ["anthropic>=1.0", "openai>=1.50"]

Después instala:

uv pip install -e ".[torch]"     # base + PyTorch
uv pip install -e ".[llm]"       # base + SDKs de LLMs
uv pip install -e ".[torch,llm]" # todo

Lockfiles

Un lockfile fija todas las dependencias (incluidas las transitivas) a versiones exactas. Garantiza la reproducibilidad: quien instale desde el lockfile obtendrá exactamente los mismos paquetes.

# uv genera uv.lock automáticamente cuando usas uv add
uv add numpy

# Alternativa estilo pip-tools
uv pip compile pyproject.toml -o requirements.lock
uv pip install -r requirements.lock

Sube el lockfile a git. Quien clone tu proyecto instalará desde él y tendrá versiones idénticas.

Rangos frente a versiones exactas. En pyproject.toml declaras rangos (numpy>=1.26): lo que tu código acepta. En el lockfile quedan versiones exactas (numpy==2.1.3): lo que de verdad se instaló. Necesitas ambos.

Errores habituales

1. Instalar de forma global

pip install torch  # MAL: instala en el Python del sistema

source .venv/bin/activate
pip install torch  # BIEN: instala en el entorno virtual

Comprueba a dónde van tus paquetes:

which python       # debería mostrar .venv/bin/python, no /usr/bin/python
which pip          # debería mostrar .venv/bin/pip

2. Mezclar pip y conda

conda create -n miambiente python=3.12
conda activate miambiente
conda install pytorch -c pytorch
pip install otro-paquete     # MAL: puede romper el control de dependencias de conda
conda install otro-paquete   # BIEN: deja que conda lo gestione todo

Si no te queda más remedio que usar pip dentro de conda (hay paquetes que solo están en pip), instala primero todo lo de conda y deja pip para el final.

3. Olvidar activar el entorno

python train.py           # usa el Python del sistema: faltan paquetes
source .venv/bin/activate
python train.py           # usa el Python del proyecto: paquetes encontrados

Tu prompt debería mostrar el nombre del entorno:

(.venv) $ python train.py

4. Subir .venv a git

echo ".venv/" >> .gitignore

Los entornos virtuales ocupan entre 200 MB y 2 GB, y son locales: no se pueden llevar de una máquina a otra. Sube pyproject.toml y el lockfile en su lugar.

5. Versiones de CUDA incompatibles

nvidia-smi                # muestra la versión de CUDA del driver (p. ej., 12.4)
python -c "import torch; print(torch.version.cuda)"  # muestra la versión de CUDA de PyTorch

# Deben ser compatibles:
# la versión de CUDA de PyTorch debe ser <= la versión de CUDA del driver.

En la práctica

Descarga preparar_entorno.sh desde «Archivos de la lección», guárdalo en tu carpeta del curso (por ejemplo, mi-curso-ia) y ejecútalo desde ella:

cd mi-curso-ia
bash preparar_entorno.sh

Crea un .venv en esa carpeta (con uv si lo tienes y, si no, con venv), instala las dependencias principales (numpy, matplotlib, jupyter, scikit-learn y pandas), comprueba que todas se importan bien y añade .venv/ a tu .gitignore para que nunca lo subas a git.

¿Cómo sabe Python si está dentro de un entorno virtual? Compara sys.prefix (el Python que se está usando) con sys.base_prefix (el Python sobre el que se creó). Pruébalo aquí: en el navegador no hay entorno virtual, así que verás que coinciden. Copia el mismo código en tu ordenador con el .venv activado y verás que cambian:

import sys

print("Python en uso:      ", sys.prefix)
print("Python de base:     ", sys.base_prefix)
dentro = sys.prefix != sys.base_prefix
print("¿Entorno virtual?   ", "sí" if dentro else "no")

Retos para tu ordenador

  1. Ejecuta preparar_entorno.sh y comprueba que todas las verificaciones pasan
  2. Crea un segundo entorno virtual, instala en él otra versión de numpy y confirma que los dos entornos están aislados
  3. Escribe un pyproject.toml para un proyecto que necesite PyTorch y el SDK de Anthropic
  4. Instala a propósito un paquete de forma global (sin activar ningún entorno), mira a dónde va y desinstálalo

Glosario de la lección

Término Como se suele decir Qué es exactamente
Entorno virtual «Un venv» Una carpeta aislada con un intérprete de Python y sus paquetes, separada del Python del sistema
Lockfile «Dependencias fijadas» Un archivo con cada paquete y su versión exacta, que garantiza instalaciones idénticas en cualquier máquina
pyproject.toml «El nuevo setup.py» El archivo estándar de configuración de proyectos Python
Dependencia transitiva «Una dependencia de una dependencia» Si A depende de B y B depende de C, C es una dependencia transitiva de A
CUDA incompatible «Mi GPU no funciona» PyTorch se compiló para una versión de CUDA distinta de la que soporta el driver de tu GPU

🧪 Practica esta lección

En el curso, esta lección incluye ejercicios interactivos con corrección automática y ejemplos de Python que ejecutas en tu navegador, sin instalar nada. Es gratis.

Practicar gratis en el curso →

📥 Archivos de la lección