Entornos virtuales y dependencias
Un proyecto, un entorno: la regla que acaba con los conflictos de versiones.
Qué vas a aprender
- Crear entornos virtuales aislados con
uv,venvoconda - Escribir un
pyproject.tomlcon 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 installglobal 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.tomldeclaras 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
- Ejecuta
preparar_entorno.shy comprueba que todas las verificaciones pasan - Crea un segundo entorno virtual, instala en él otra versión de numpy y confirma que los dos entornos están aislados
- Escribe un
pyproject.tomlpara un proyecto que necesite PyTorch y el SDK de Anthropic - 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 |