Phase 00 - Lesson 06

Entornos de Python

El infierno de dependencias es real. Los entornos virtuales son la cura.

Tipo: Build Lenguajes: Python Requisitos previos: Fase 0, Lección 01 Tiempo: ~30 minutos

Objetivos de Aprendizaje

  • Crear entornos virtuales aislados usando uv, venv o conda
  • Escribir un pyproject.toml con grupos de dependencias opcionales y generar lockfiles para reproducibilidad
  • Diagnosticar y corregir trampas comunes: instalaciones globales, mezcla de pip/conda, incompatibilidades de versión de CUDA
  • Implementar una estrategia de entorno por fase para proyectos con dependencias en conflicto

El Problema

Instalas PyTorch 2.4 para un proyecto de fine-tuning. A la semana siguiente, un proyecto distinto necesita PyTorch 2.1 porque su build de CUDA está fijado. Actualizas globalmente y el primer proyecto se rompe. Haces el downgrade y el segundo se rompe.

Esto es el infierno de dependencias. Sucede constantemente en el trabajo con IA/ML porque:

  • PyTorch, JAX y TensorFlow traen cada uno sus propios bindings de CUDA
  • Las bibliotecas de modelos fijan versiones específicas de frameworks
  • Un pip install global sobrescribe lo que hubiera antes
  • Los builds de 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.

El Concepto

graph TD
    subgraph without["Without virtual environments"]
        SP[System Python] --> T24["torch 2.4.0 (CUDA 12.4)\nProject A needs this"]
        SP --> T21["torch 2.1.0 (CUDA 11.8)\nProject B needs this"]
        SP --> CONFLICT["CONFLICT: only one\ntorch version can exist"]
    end

    subgraph with["With virtual environments"]
        PA["Project A (.venv/)"] --> PA1["torch 2.4.0 (CUDA 12.4)"]
        PA --> PA2["transformers 4.44"]
        PB["Project B (.venv/)"] --> PB1["torch 2.1.0 (CUDA 11.8)"]
        PB --> PB2["diffusers 0.28"]
    end

Build It

Opción 1: uv venv (Recomendado)

uv es el gestor de paquetes de Python más rápido (10-100x más rápido que pip). Maneja entornos virtuales, versiones de Python y resolución de dependencias en una sola herramienta.

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

uv python install 3.12

cd your-project
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 my-ai-project
cd my-ai-project
uv add torch numpy matplotlib

Opción 2: venv (Integrado)

Si no puedes instalar uv, Python ya viene con venv:

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

pip install torch numpy

Más lento que uv, pero funciona en cualquier lugar donde Python esté instalado.

Opción 3: conda (Cuando lo necesitas)

Conda gestiona dependencias que no son de Python, como toolkits de CUDA, cuDNN y bibliotecas C. Úsalo cuando:

  • Necesitas una versión específica del toolkit de CUDA sin instalarla en todo el sistema
  • Estás en un cluster compartido donde no puedes instalar paquetes del sistema
  • Las instrucciones de instalación de una biblioteca dicen "usa conda"
# Install miniconda (not the full Anaconda)
curl -LsSf https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -o miniconda.sh
bash miniconda.sh -b

conda create -n myproject python=3.12
conda activate myproject

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 en un entorno conda causa conflictos de dependencias dolorosos de depurar.

Para Este Curso: Estrategia por Fase

Podrías crear un único entorno para todo el curso. No lo hagas. Fases distintas necesitan dependencias distintas (a veces en conflicto).

Estrategia:

ai-engineering-from-scratch/
├── .venv/                    <-- shared lightweight env for phases 0-3
├── phases/
│   ├── 04-neural-networks/
│   │   └── .venv/            <-- PyTorch env
│   ├── 05-cnns/
│   │   └── .venv/            <-- same PyTorch env (symlink or shared)
│   ├── 08-transformers/
│   │   └── .venv/            <-- might need different transformer versions
│   └── 11-llm-apis/
│       └── .venv/            <-- API SDKs, no torch needed

El script en code/env_setup.sh crea el entorno base para este curso.

Fundamentos de pyproject.toml

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

[project]
name = "ai-engineering-from-scratch"
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>=0.39", "openai>=1.50"]

Luego instala:

uv pip install -e ".[torch]"    # base + PyTorch
uv pip install -e ".[llm]"     # base + LLM SDKs
uv pip install -e ".[torch,llm]" # everything

Lockfiles

Un lockfile fija cada dependencia (incluidas las transitivas) en versiones exactas. Esto garantiza reproducibilidad: cualquiera que instale desde el lockfile obtiene exactamente los mismos paquetes.

# uv generates uv.lock automatically when using uv add
uv add numpy

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

Confirma tu lockfile en git. Cuando alguien clone el repositorio, instalará desde el lockfile y obtendrá versiones idénticas.

Errores Comunes

1. Instalar globalmente

pip install torch  # BAD: installs to system Python

source .venv/bin/activate
pip install torch  # GOOD: installs to virtual environment

Verifica adónde van tus paquetes:

which python       # should show .venv/bin/python, not /usr/bin/python
which pip           # should show .venv/bin/pip

2. Mezclar pip y conda

conda create -n myenv python=3.12
conda activate myenv
conda install pytorch -c pytorch
pip install some-other-package   # BAD: can break conda's dependency tracking
conda install some-other-package # GOOD: let conda manage everything

Si debes usar pip dentro de conda (algunos paquetes son solo de pip), instala primero todos los paquetes de conda y luego los paquetes de pip al final.

3. Olvidar activar

python train.py           # uses system Python, missing packages
source .venv/bin/activate
python train.py           # uses project Python, packages found

El prompt de tu shell debería mostrar el nombre del entorno:

(.venv) $ python train.py

4. Confirmar el .venv en git

echo ".venv/" >> .gitignore

Los entornos virtuales pesan entre 200MB y 2GB. Son locales, no portables entre máquinas. En su lugar, confirma el pyproject.toml y el lockfile.

5. Incompatibilidad de versión de CUDA

nvidia-smi                # shows driver CUDA version (e.g., 12.4)
python -c "import torch; print(torch.version.cuda)"  # shows PyTorch CUDA version

# These must be compatible.
# PyTorch CUDA version must be <= driver CUDA version.

Use It

Ejecuta el script de configuración para crear el entorno de tu curso:

bash phases/00-setup-and-tooling/06-python-environments/code/env_setup.sh

Esto crea un .venv en la raíz del repositorio con las dependencias principales instaladas y verificadas.

Ejercicios

  1. Ejecuta env_setup.sh y verifica que todas las comprobaciones pasen
  2. Crea un segundo entorno virtual, instala una versión distinta de numpy en él y confirma que los dos entornos están aislados
  3. Escribe un pyproject.toml para un proyecto que necesite tanto PyTorch como el Anthropic SDK
  4. Instala deliberadamente un paquete globalmente (sin activar un venv), observa adónde va y luego desinstálalo

Términos Clave

Término Lo que dice la gente Lo que realmente significa
Entorno virtual "Un venv" Un directorio aislado que contiene un intérprete de Python y paquetes, separado del Python del sistema
Lockfile "Dependencias fijadas" Un archivo que lista cada paquete y su versión exacta, garantizando instalaciones idénticas entre máquinas
pyproject.toml "El nuevo setup.py" El archivo estándar de configuración de proyectos de Python, que reemplaza setup.py/setup.cfg/requirements.txt
Dependencia transitiva "Una dependencia de una dependencia" El paquete B depende de C; si instalas A que depende de B, C es una dependencia transitiva de A
Incompatibilidad de CUDA "Mi GPU no funciona" PyTorch fue compilado para una versión de CUDA distinta de la que soporta el driver de tu GPU
0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).