El recorrido de ingeniero de IA, y entornos de desarrollo con uv
Instalar Python, por qué uv en lugar de pip, y un entorno aislado y reproducible para cada proyecto con uv init, uv add y uv run — más el intérprete correcto en tu editor.
¿Cómo quieres aprender?
El problema que vamos a resolver
Un nuevo ingeniero de IA se une a un equipo. La tarea del primer día es sencilla: hacer que el proyecto funcione en su propio portátil. El README dice «ejecuta python main.py». Lo ejecuta y obtiene ModuleNotFoundError: No module named 'httpx'. En la máquina de la persona que escribió el proyecto, el mismo comando funciona perfectamente.
Al investigar, resulta que durante dos años, todos los paquetes que cualquier proyecto de esa persona ha necesitado se han ido acumulando en el mismo Python. Qué paquetes necesita este proyecto no está escrito en ninguna parte; solo existe el «en mi máquina funciona». El nuevo compañero pasa medio día buscando e instalando paquetes uno por uno, y al final uno de ellos es otra versión, así que los resultados también cambian.
Los equipos profesionales tienen una sola respuesta para esto: cada proyecto tiene su propio entorno aislado, y lo que contiene ese entorno está escrito en un archivo, de modo que cualquiera puede crear exactamente el mismo entorno con un solo comando. Eso es lo que construimos en este capítulo — con uv — y es lo que usaremos durante el resto del curso.
Al terminar este capítulo podrás
- Instalar Python tanto con el instalador normal como con
uv python install, y explicar en qué se diferencian - Explicar qué es
pipy por qué este curso usauven su lugar - Crear y ejecutar un entorno de proyecto aislado con
uv init,uv add,uv runyuv venv - Mostrar con un ejemplo por qué los proyectos no deberían ejecutarse con el Python del sistema
- Seleccionar el intérprete propio del proyecto en VS Code o PyCharm
Requisitos previos: cambiar de carpeta en una terminal (cd) y ejecutar un comando. Es el primer capítulo del curso, así que no hace falta nada más.
Cómo funciona este recorrido
Este curso es un recorrido profesional. Cada capítulo es como una clase, y cada uno termina con una tarea que se ejecuta en tu propia máquina. Los primeros capítulos sientan las bases del trabajo profesional — entornos, Git, estructura de proyectos, configuración. Después vienen Python limpio, pruebas, APIs, bases de datos, RAG, seguridad y despliegue.
Conviene decirlo desde el principio: en una empresa, el código de un ingeniero de IA no se acepta solo porque «funciona». Que otra persona pueda ejecutarlo en su máquina, que alguien pueda revisarlo, que alguien lo entienda dentro de seis meses — eso también forma parte del trabajo. Por eso, cada tarea práctica de este curso está planteada como si fuera a entrar en el repositorio de un equipo real. Y el primer paso de ese hábito es el entorno.
Instalar Python: dos caminos
Camino uno — el instalador normal. Descarga el instalador de Python 3.12 desde python.org y ejecútalo. En Windows, marca Add python.exe to PATH en la primera pantalla; si no lo haces, la terminal no reconocerá el comando python. En macOS basta con ejecutar el .pkg de python.org. En Linux, python3 suele estar ya instalado, y más abajo hay una advertencia al respecto.
Para comprobarlo:
python --version
Python 3.12.0En macOS y Linux, el comando suele ser python3 --version.
Camino dos — con uv. uv es una única herramienta que se encarga de las versiones de Python, de los entornos de proyecto y de los paquetes. Primero instala uv. En macOS y Linux:
curl -LsSf https://astral.sh/uv/install.sh | shEn Windows PowerShell:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"Luego abre una terminal nueva:
uv --version
uv 0.9.1 (9887ef5bd 2025-10-09)Tu número de versión puede ser distinto. Ahora, Python:
uv python install 3.12
Installed Python 3.12.11 in 27.42s
+ cpython-3.12.11-windows-x86_64-none (python3.12.exe)La hora y el nombre de la plataforma del final serán diferentes en tu máquina. Fíjate en que el Python que instala uv vive en una carpeta propia — no toca el Python principal de la máquina ni cambia PATH.
Los dos caminos pueden convivir, y ambos sirven para este curso. La diferencia: el instalador normal te da un Python para todo el ordenador; uv python install te da Pythons que cada proyecto elige según lo que necesite. Un proyecto quiere 3.12, otro 3.13 — ninguno estorba al otro.
Qué es pip, y por qué usamos uv
Los paquetes externos de Python — httpx, pydantic, fastapi — viven en un repositorio llamado PyPI. La herramienta tradicional para descargarlos es pip, que viene con Python. Casi todos los tutoriales de internet dicen pip install ....
pip funciona bien, pero hace una sola cosa: instalar paquetes. Y los instala en el Python con el que se ejecutó. Para un proyecto profesional, todo lo demás necesita una herramienta aparte:
- obtener la versión correcta de Python — otra herramienta
- crear y activar un entorno aislado —
python -m venv, y luegoactivatea mano - registrar lo que necesita el proyecto — a mano, en un archivo, y muchas veces se olvida
- fijar exactamente qué versión de cada paquete se usó (un lockfile) — otra herramienta más
uv hace las cuatro cosas en una sola herramienta, y mucho más rápido. Lo más importante: cuando añades algo con uv add, se escribe automáticamente en el archivo del proyecto. «Lo instalé, pero se me olvidó anotarlo» — la causa de los problemas del nuevo compañero — no puede pasar de esta forma.
Por eso, siempre que aparezcan paquetes o entornos en este curso, la herramienta es uv. Cuando veas pip install en otra parte, el equivalente en uv es casi siempre uv add.
Por qué el Python del sistema no es el lugar para los proyectos
El «Python del sistema» es el Python instalado directamente en el ordenador — el que se ejecuta cuando escribes python en una terminal sin activar ningún entorno. Instalar los paquetes de un proyecto ahí causa tres problemas:
- Todos comparten la misma habitación. Un proyecto necesita
pydantic1, otro necesita la 2. El Python del sistema solo puede tener una, así que arreglar un proyecto rompe el otro. - Las dependencias se vuelven invisibles. El paquete ya estaba instalado para algún proyecto antiguo, así que el nuevo proyecto funciona — pero en ninguna parte del proyecto se dice que necesita ese paquete. No aparece ningún error en tu máquina; el error aparece en la máquina de un compañero, o en el servidor.
- El sistema operativo lo usa. En macOS y Linux, algunas herramientas del sistema se ejecutan con ese Python. Cambiar sus paquetes puede romperlas — por eso las versiones recientes de Linux bloquean instalar directamente en el Python del sistema.
El segundo problema es el más peligroso porque es silencioso. El Python del sistema de la máquina en la que se escribió este capítulo todavía tiene httpx, pydantic y rich de trabajos antiguos. Así que cualquier script «funciona» allí — y justo por eso no hay forma de saber, a partir de esa ejecución, qué necesita de verdad un script.
La creencia equivocada es: «Funciona en mi máquina, así que está bien». Un script que funciona con el Python del sistema solo demuestra que, en algún momento, el paquete se instaló en tu máquina. Lo que el proyecto necesita en realidad solo se demuestra cuando todo se instala en un entorno vacío a partir del archivo del proyecto, y entonces el script se ejecuta.
Un primer proyecto con uv
Desde una carpeta de trabajo:
uv init hello-ai --python 3.12
Initialized project `hello-ai` at `D:\ai-lab\hello-ai`(La ruta del final será la de tu carpeta; los ejemplos de salida de este capítulo acortan las rutas.) uv init crea una carpeta nueva, y dentro de ella:
hello-ai/
├── .git/
├── .gitignore
├── .python-version
├── README.md
├── main.py
└── pyproject.tomlEl más importante de estos archivos es pyproject.toml — la tarjeta de identidad del proyecto:
[project]
name = "hello-ai"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []dependencies = [] — el proyecto todavía no necesita ningún paquete externo. .python-version contiene solo 3.12: el Python con el que se ejecuta este proyecto. Y uv init ha creado por ti un repositorio Git y un .gitignore — entran en juego en el siguiente capítulo.
Ahora ejecútalo:
cd hello-ai
uv run main.py
Using CPython 3.12.11
Creating virtual environment at: .venv
Hello from hello-ai!La primera vez, uv run creó por su cuenta una carpeta .venv — que es el entorno aislado del proyecto — y luego ejecutó main.py con el Python de ese entorno. No tuviste que activar nada.
uv add: añadir un paquete, y dejarlo por escrito
Casi todos los proyectos en los que trabaja un ingeniero de IA llaman a alguna API, así que el primer paquete es el cliente HTTP httpx, junto con python-dotenv para leer archivos .env:
uv add httpx python-dotenv
Resolved 9 packages in 119ms
Installed 8 packages in 92ms
+ anyio==4.15.1
+ certifi==2026.7.22
+ h11==0.16.0
+ httpcore==1.0.9
+ httpx==0.28.1
+ idna==3.20
+ python-dotenv==1.2.3
+ typing-extensions==4.16.0Pediste dos paquetes y obtuviste ocho — los demás son dependencias de httpx, que uv calculó por su cuenta. Los números de versión pueden ser más nuevos cuando lo hagas tú.
Ahora mira pyproject.toml:
[project]
name = "hello-ai"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"httpx>=0.28.1",
"python-dotenv>=1.2.3",
]Un solo comando hizo tres cosas: los paquetes se instalaron en .venv, pyproject.toml ahora registra que el proyecto los necesita, y apareció un archivo nuevo llamado uv.lock que fija la versión exacta de los ocho paquetes. Los lockfiles se verán con detalle un poco más adelante en el curso; por ahora basta con saber que un compañero que clone el repositorio y ejecute uv sync obtendrá exactamente estas ocho versiones.
Para quitar algo, uv remove:
uv remove python-dotenv
Resolved 8 packages in 21ms
Uninstalled 1 package in 11ms
- python-dotenv==1.2.3Esto también funciona en los dos sitios: lo quita de .venv y lo borra de pyproject.toml.
uv venv, y activar a mano
uv run crea y usa el entorno por ti, así que en este curso casi siempre basta. Pero a veces solo necesitas un entorno vacío — por ejemplo, en un proyecto antiguo que todavía no tiene pyproject.toml. Entonces:
uv venv --python 3.12
Using CPython 3.12.11
Creating virtual environment at: .venv
Activate with: .venv\Scripts\activateEsa última línea es de Windows PowerShell. Aquí es donde los sistemas operativos difieren:
# Windows (PowerShell)
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activateUna vez activo, el prompt empieza con (hello-ai) o (.venv), y un comando python normal ejecuta el Python de ese entorno. Para salir, deactivate. Recuerda que con uv run nada de esto hace falta — esa es su ventaja, y escribir uv run en el README de un equipo es la opción segura, porque no existe el estado de «se me olvidó activar».
Apuntar el editor al Python del proyecto
El programa se ejecuta en la terminal, pero el editor muestra una línea roja bajo import httpx — casi siempre esto significa que el editor está mirando otro Python.
VS Code: instala la extensión Python de Microsoft. Luego abre la carpeta del proyecto, pulsa Ctrl + Shift + P (Cmd + Shift + P en macOS) → Python: Select Interpreter → elige el Python dentro de .venv. Si no aparece en la lista, usa Enter interpreter path y señálalo: .venv\Scripts\python.exe en Windows, .venv/bin/python en macOS/Linux.
PyCharm: Settings → Project → Python Interpreter → Add Interpreter → Add Local Interpreter → elige un entorno existente e indica la misma ruta. Las versiones recientes también ofrecen directamente un tipo de entorno uv.
La forma más fácil de estar seguro de qué Python usa el editor es ejecutar esto en la terminal integrada del editor:
import sys
print(sys.executable)La ruta debería terminar dentro del .venv de tu proyecto — por ejemplo, ...\hello-ai\.venv\Scripts\python.exe. El principio de la ruta depende de tu carpeta, así que aquí no se muestra la salida completa.
Un ejemplo completo
En el proyecto hello-ai, crea un archivo llamado env_check.py. Es un pequeño script de «comprobación del entorno» — cuando alguien nuevo se une a un equipo, ejecutar algo así primero confirma que todo está donde debe:
import sys
from importlib.metadata import version
from pathlib import Path
def main() -> None:
in_venv = sys.prefix != sys.base_prefix
print(f"Python : {sys.version_info.major}.{sys.version_info.minor}")
print(f"In a venv : {in_venv}")
print(f"Env folder : {Path(sys.prefix).name}")
import httpx # installed with `uv add httpx`
print(f"httpx : {version('httpx')}")
print(f"Client ready: {httpx.Client is not None}")
print("Hello, AI engineer.")
if __name__ == "__main__":
main()Ejecútalo desde dentro del proyecto:
uv run env_check.pyPython : 3.12
In a venv : True
Env folder : .venv
httpx : 0.28.1
Client ready: True
Hello, AI engineer.Ahora ejecutemos el mismo archivo en un entorno vacío. El archivo se copió a otra carpeta, allí se creó un entorno con uv venv --python 3.12, y el archivo se ejecutó directamente con el Python de ese entorno (.venv\Scripts\python env_check.py en Windows, .venv/bin/python env_check.py en macOS/Linux):
Python : 3.12
In a venv : True
Env folder : .venv
Traceback (most recent call last):
File "env_check.py", line 20, in <module>
main()
File "env_check.py", line 12, in main
import httpx # installed with `uv add httpx`
^^^^^^^^^^^^
ModuleNotFoundError: No module named 'httpx'(En tu máquina, el traceback muestra la ruta completa del archivo; aquí solo se conserva el nombre.)
Algunas decisiones de este script merecen atención.
sys.prefix != sys.base_prefix — el propio Python sabe si se está ejecutando dentro de un entorno virtual. sys.base_prefix es el Python base a partir del cual se creó el entorno, y sys.prefix es el que se está ejecutando ahora. Si son distintos, estás dentro de un entorno.
El nombre de la carpeta, no la ruta completa — Path(sys.prefix).name imprime solo la última parte, .venv. La ruta completa es distinta en cada máquina; el nombre es el mismo para todos. Cuanto menos específica de una máquina sea la salida de un script de comprobación, más fácil es compararla en el chat del equipo.
import httpx en medio de la función — normalmente los imports van al principio del archivo, y así debe ser. Aquí se colocó a propósito en medio, para que, en un entorno vacío, las tres primeras líneas se impriman antes del error. La salida del error cuenta su propia historia: Python 3.12 está bien, hay un entorno activo, pero ese entorno no tiene httpx. La solución es uv add httpx — o, si el pyproject.toml del proyecto ya lo lista, uv sync.
version('httpx') — importlib.metadata es la forma estándar de leer la versión de un paquete. No todos los paquetes tienen un __version__, pero todo paquete instalado tiene metadatos.
Cuando falla
The term 'uv' is not recognized as the name of a cmdlet, function, script file, or operable program (en macOS/Linux, uv: command not found) uv está instalado, pero la terminal en la que escribes se abrió antes de la instalación, así que no conoce el nuevo PATH. Cierra y vuelve a abrir la terminal (y, en VS Code, todo el editor).
error: No pyproject.toml found in current directory or any parent directory Ejecutaste uv add fuera de una carpeta de proyecto. uv add escribe en el archivo del proyecto, así que sin proyecto no hay dónde escribir. Entra en el proyecto con cd, o ejecuta uv init primero si es nuevo.
ModuleNotFoundError: No module named 'httpx' El Python que ejecuta el script no tiene el paquete. Dos causas habituales: el paquete nunca se añadió con uv add, o el script se ejecutó con python normal en lugar de con uv run, así que se ejecutó el Python del sistema en vez del entorno del proyecto. Ejecútalo con uv run env_check.py.
error: Failed to spawn: hello.py seguido de Caused by: program not found Le diste a uv run un nombre de archivo que no está en la carpeta actual — normalmente un error de escritura, o estás en la carpeta equivocada. Al no encontrar el archivo, uv buscó un programa con ese nombre, por eso el mensaje resulta raro.
× No solution found when resolving dependencies seguido de Because htpx was not found in the package registry ... Un error de escritura en el nombre del paquete (htpx). La buena noticia es que un uv add fallido no cambia nada — pyproject.toml y uv.lock quedan como estaban. Corrige la escritura y vuelve a ejecutarlo.
.venv\Scripts\activate : File ... cannot be loaded because running scripts is disabled on this system Una política de seguridad de PowerShell. Ejecuta una vez Set-ExecutionPolicy -Scope CurrentUser RemoteSigned y abre una terminal nueva — o no actives el entorno y ejecuta todo con uv run.
Paso 4 de 6 — Predice
Comprueba lo que has entendido
Este archivo se guarda como check.py en el proyecto hello-ai y se ejecuta con uv run check.py. ¿Qué se imprime?
import sys
print(sys.prefix != sys.base_prefix)
print(sys.version_info.major)- A`.venv`, y luego `3.12`
- B`True`, y luego `3`
- C`True`, y luego `12`
- D`False`, y luego `3`
El pyproject.toml del proyecto lista httpx, y uv.lock está en el repositorio. Aun así, un compañero nuevo que sigue el README en un portátil recién estrenado obtiene ModuleNotFoundError: No module named 'httpx'. ¿Dónde está el error en el README?
# README of a team project, "How to run" section:
# 1. git clone <repo-url>
# 2. cd summarizer
# 3. python main.py
import httpx
print("client:", httpx.Client.__name__)- AFalta un paso que ejecute `uv init` después de clonar el repositorio
- BEl compañero primero debe ejecutar `uv add httpx`, y luego `python main.py`
- CLa línea `import httpx` debe pasar de la parte superior del archivo a una función `main()`
- DEl paso 3 ejecuta el Python del sistema; debería decir `uv run main.py`, que construye `.venv` a partir de `pyproject.toml` y `uv.lock` y ejecuta dentro de él
Después de uv init y uv add, el proyecto tiene pyproject.toml, uv.lock, .python-version y .venv. ¿Cuáles de estos van en el repositorio Git del equipo?
- ATodo menos `.python-version`, porque la versión de Python es una elección personal
- B`pyproject.toml`, `uv.lock` y `.python-version` van dentro; `.venv` no
- CLos cuatro, incluido `.venv`, para que los compañeros no tengan que instalar nada
- DSolo `pyproject.toml`; `uv.lock` se genera, así que también lo dejamos fuera
Jugar es parte de Pro
+30 XP te esperan
Juega este capítulo con Pro
Leer es gratis y el capítulo está abierto entero. Los primeros 5 capítulos de cada curso gratuito se pueden jugar gratis. Desde el capítulo 6, responder las preguntas, ganar XP y hacer crecer tu racha es parte de Pro.
Desbloquea el juego con ProTu turno
Con uv y Python 3.12 listos en tu máquina, crea un proyecto nuevo:
- Crea el proyecto con
uv init my-first-agent --python 3.12, y añade un paquete conuv add httpx - Escribe el archivo
env_check.pyde arriba en el proyecto tal cual, y ejecútalo conuv run env_check.py - Abre
pyproject.tomly muestra quehttpxaparece endependencies, y que se creó un archivouv.locken el proyecto - Abre el proyecto en VS Code o PyCharm y selecciona el
.venvdel proyecto como intérprete, para que no haya una línea roja en la líneaimport httpx
Salida esperada (la versión de httpx puede ser más nueva cuando lo hagas tú):
Python : 3.12
In a venv : True
Env folder : .venv
httpx : 0.28.1
Client ready: True
Hello, AI engineer.Luego, rómpelo a propósito: ejecuta uv remove httpx y vuelve a ejecutar uv run env_check.py. Anota hasta dónde imprime, qué error aparece y qué cambió en pyproject.toml. Después, arréglalo con uv add httpx. Este ciclo de romper y reparar dura dos minutos, pero en la primera semana de tu primer trabajo es lo que más tiempo te va a ahorrar.
Paso 6 de 6
Reto — el quiz del capítulo
Diez preguntas de fácil a difícil. Las últimas son difíciles a propósito.
Juega con Pro