# Entornos Virtuales { #virtual-environments } Cuando trabajas en proyectos de Python probablemente deberías usar un **entorno virtual** (o un mecanismo similar) para aislar los paquetes que instalas para cada proyecto. /// info | Información Si ya sabes sobre entornos virtuales, cómo crearlos y usarlos, podrías querer saltar esta sección. 🤓 /// /// tip | Consejo Un **entorno virtual** es diferente de una **variable de entorno**. Una **variable de entorno** es una variable en el sistema que puede ser usada por programas. Un **entorno virtual** es un directorio con algunos archivos en él. /// /// info | Información Esta página te enseñará cómo usar **entornos virtuales** y cómo funcionan. Si estás listo para adoptar una **herramienta que gestiona todo** por ti (incluyendo la instalación de Python), prueba uv. /// ## Crea un Proyecto { #create-a-project } Primero, crea un directorio para tu proyecto. Lo que normalmente hago es crear un directorio llamado `code` dentro de mi directorio de usuario. Y dentro de eso creo un directorio por proyecto.
```console // Ve al directorio principal $ cd // Crea un directorio para todos tus proyectos de código $ mkdir code // Entra en ese directorio de código $ cd code // Crea un directorio para este proyecto $ mkdir awesome-project // Entra en ese directorio del proyecto $ cd awesome-project ```
## Crea un Entorno Virtual { #create-a-virtual-environment } Cuando empiezas a trabajar en un proyecto de Python **por primera vez**, crea un entorno virtual **dentro de tu proyecto**. /// tip | Consejo Solo necesitas hacer esto **una vez por proyecto**, no cada vez que trabajas. /// //// tab | `venv` Para crear un entorno virtual, puedes usar el módulo `venv` que viene con Python.
```console $ python -m venv .venv ```
/// details | Qué significa ese comando * `python`: usa el programa llamado `python` * `-m`: llama a un módulo como un script, indicaremos cuál módulo a continuación * `venv`: usa el módulo llamado `venv` que normalmente viene instalado con Python * `.venv`: crea el entorno virtual en el nuevo directorio `.venv` /// //// //// tab | `uv` Si tienes instalado `uv`, puedes usarlo para crear un entorno virtual.
```console $ uv venv ```
/// tip | Consejo Por defecto, `uv` creará un entorno virtual en un directorio llamado `.venv`. Pero podrías personalizarlo pasando un argumento adicional con el nombre del directorio. /// //// Ese comando crea un nuevo entorno virtual en un directorio llamado `.venv`. /// details | `.venv` u otro nombre Podrías crear el entorno virtual en un directorio diferente, pero hay una convención de llamarlo `.venv`. /// ## Activa el Entorno Virtual { #activate-the-virtual-environment } Activa el nuevo entorno virtual para que cualquier comando de Python que ejecutes o paquete que instales lo utilicen. /// tip | Consejo Haz esto **cada vez** que inicies una **nueva sesión de terminal** para trabajar en el proyecto. /// //// tab | Linux, macOS
```console $ source .venv/bin/activate ```
//// //// tab | Windows PowerShell
```console $ .venv\Scripts\Activate.ps1 ```
//// //// tab | Windows Bash O si usas Bash para Windows (por ejemplo, Git Bash):
```console $ source .venv/Scripts/activate ```
//// /// tip | Consejo Cada vez que instales un **nuevo paquete** en ese entorno, **activa** el entorno de nuevo. Esto asegura que si usas un programa de **terminal (CLI)** instalado por ese paquete, uses el de tu entorno virtual y no cualquier otro que podría estar instalado globalmente, probablemente con una versión diferente a la que necesitas. /// ## Verifica que el Entorno Virtual esté Activo { #check-the-virtual-environment-is-active } Verifica que el entorno virtual esté activo (el comando anterior funcionó). /// tip | Consejo Esto es **opcional**, pero es una buena forma de **revisar** que todo está funcionando como se esperaba y estás usando el entorno virtual que pretendes. /// //// tab | Linux, macOS, Windows Bash
```console $ which python /home/user/code/awesome-project/.venv/bin/python ```
Si muestra el binario de `python` en `.venv/bin/python`, dentro de tu proyecto (en este caso `awesome-project`), entonces funcionó. 🎉 //// //// tab | Windows PowerShell
```console $ Get-Command python C:\Users\user\code\awesome-project\.venv\Scripts\python ```
Si muestra el binario de `python` en `.venv\Scripts\python`, dentro de tu proyecto (en este caso `awesome-project`), entonces funcionó. 🎉 //// ## Actualiza `pip` { #upgrade-pip } /// tip | Consejo Si usas `uv` usarías eso para instalar cosas en lugar de `pip`, por lo que no necesitas actualizar `pip`. 😎 /// Si estás usando `pip` para instalar paquetes (viene por defecto con Python), deberías **actualizarlo** a la última versión. Muchos errores exóticos al instalar un paquete se resuelven simplemente actualizando `pip` primero. /// tip | Consejo Normalmente harías esto **una vez**, justo después de crear el entorno virtual. /// Asegúrate de que el entorno virtual esté activo (con el comando anterior) y luego ejecuta:
```console $ python -m pip install --upgrade pip ---> 100% ```
/// tip | Consejo A veces, podrías obtener un error **`No module named pip`** al intentar actualizar pip. Si esto pasa, instala y actualiza pip usando el siguiente comando:
```console $ python -m ensurepip --upgrade ---> 100% ```
Este comando instalará pip si aún no está instalado y también se asegura de que la versión instalada de pip sea al menos tan reciente como la disponible en `ensurepip`. /// ## Añade `.gitignore` { #add-gitignore } Si estás usando **Git** (deberías), añade un archivo `.gitignore` para excluir todo en tu `.venv` de Git. /// tip | Consejo Si usaste `uv` para crear el entorno virtual, ya lo hizo por ti, puedes saltarte este paso. 😎 /// /// tip | Consejo Haz esto **una vez**, justo después de crear el entorno virtual. ///
```console $ echo "*" > .venv/.gitignore ```
/// details | Qué significa ese comando * `echo "*"`: "imprimirá" el texto `*` en el terminal (la siguiente parte cambia eso un poco) * `>`: cualquier cosa impresa en el terminal por el comando a la izquierda de `>` no debería imprimirse, sino escribirse en el archivo que va a la derecha de `>` * `.gitignore`: el nombre del archivo donde debería escribirse el texto Y `*` para Git significa "todo". Así que, ignorará todo en el directorio `.venv`. Ese comando creará un archivo `.gitignore` con el contenido: ```gitignore * ``` /// ## Instala Paquetes { #install-packages } Después de activar el entorno, puedes instalar paquetes en él. /// tip | Consejo Haz esto **una vez** al instalar o actualizar los paquetes que necesita tu proyecto. Si necesitas actualizar una versión o agregar un nuevo paquete, **harías esto de nuevo**. /// ### Instala Paquetes Directamente { #install-packages-directly } Si tienes prisa y no quieres usar un archivo para declarar los requisitos de paquetes de tu proyecto, puedes instalarlos directamente. /// tip | Consejo Es una (muy) buena idea poner los paquetes y las versiones que necesita tu programa en un archivo (por ejemplo, `requirements.txt` o `pyproject.toml`). /// //// tab | `pip`
```console $ pip install "fastapi[standard]" ---> 100% ```
//// //// tab | `uv` Si tienes `uv`:
```console $ uv pip install "fastapi[standard]" ---> 100% ```
//// ### Instala desde `requirements.txt` { #install-from-requirements-txt } Si tienes un `requirements.txt`, ahora puedes usarlo para instalar sus paquetes. //// tab | `pip`
```console $ pip install -r requirements.txt ---> 100% ```
//// //// tab | `uv` Si tienes `uv`:
```console $ uv pip install -r requirements.txt ---> 100% ```
//// /// details | `requirements.txt` Un `requirements.txt` con algunos paquetes podría verse así: ```requirements.txt fastapi[standard]==0.113.0 pydantic==2.8.0 ``` /// ## Ejecuta Tu Programa { #run-your-program } Después de activar el entorno virtual, puedes ejecutar tu programa, y usará el Python dentro de tu entorno virtual con los paquetes que instalaste allí.
```console $ python main.py Hello World ```
## Configura Tu Editor { #configure-your-editor } Probablemente usarías un editor, asegúrate de configurarlo para que use el mismo entorno virtual que creaste (probablemente lo autodetectará) para que puedas obtener autocompletado y errores en línea. Por ejemplo: * VS Code * PyCharm /// tip | Consejo Normalmente solo tendrías que hacer esto **una vez**, cuando crees el entorno virtual. /// ## Desactiva el Entorno Virtual { #deactivate-the-virtual-environment } Una vez que hayas terminado de trabajar en tu proyecto, puedes **desactivar** el entorno virtual.
```console $ deactivate ```
De esta manera, cuando ejecutes `python` no intentará ejecutarse desde ese entorno virtual con los paquetes instalados allí. ## Listo para Trabajar { #ready-to-work } Ahora estás listo para empezar a trabajar en tu proyecto. /// tip | Consejo ¿Quieres entender todo lo anterior? Continúa leyendo. 👇🤓 /// ## Por qué Entornos Virtuales { #why-virtual-environments } Para trabajar con FastAPI necesitas instalar Python. Después de eso, necesitarías **instalar** FastAPI y cualquier otro **paquete** que desees usar. Para instalar paquetes normalmente usarías el comando `pip` que viene con Python (o alternativas similares). Sin embargo, si solo usas `pip` directamente, los paquetes se instalarían en tu **entorno global de Python** (la instalación global de Python). ### El Problema { #the-problem } Entonces, ¿cuál es el problema de instalar paquetes en el entorno global de Python? En algún momento, probablemente terminarás escribiendo muchos programas diferentes que dependen de **diferentes paquetes**. Y algunos de estos proyectos en los que trabajas dependerán de **diferentes versiones** del mismo paquete. 😱 Por ejemplo, podrías crear un proyecto llamado `philosophers-stone`, este programa depende de otro paquete llamado **`harry`, usando la versión `1`**. Así que, necesitas instalar `harry`. ```mermaid flowchart LR stone(philosophers-stone) -->|requires| harry-1[harry v1] ``` Luego, en algún momento después, creas otro proyecto llamado `prisoner-of-azkaban`, y este proyecto también depende de `harry`, pero este proyecto necesita **`harry` versión `3`**. ```mermaid flowchart LR azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] ``` Pero ahora el problema es, si instalas los paquetes globalmente (en el entorno global) en lugar de en un **entorno virtual local**, tendrás que elegir qué versión de `harry` instalar. Si deseas ejecutar `philosophers-stone` necesitarás primero instalar `harry` versión `1`, por ejemplo con:
```console $ pip install "harry==1" ```
Y entonces terminarías con `harry` versión `1` instalada en tu entorno global de Python. ```mermaid flowchart LR subgraph global[global env] harry-1[harry v1] end subgraph stone-project[philosophers-stone project] stone(philosophers-stone) -->|requires| harry-1 end ``` Pero luego si deseas ejecutar `prisoner-of-azkaban`, necesitarás desinstalar `harry` versión `1` e instalar `harry` versión `3` (o simplemente instalar la versión `3` automáticamente desinstalaría la versión `1`).
```console $ pip install "harry==3" ```
Y entonces terminarías con `harry` versión `3` instalada en tu entorno global de Python. Y si intentas ejecutar `philosophers-stone` de nuevo, hay una posibilidad de que **no funcione** porque necesita `harry` versión `1`. ```mermaid flowchart LR subgraph global[global env] harry-1[harry v1] style harry-1 fill:#ccc,stroke-dasharray: 5 5 harry-3[harry v3] end subgraph stone-project[philosophers-stone project] stone(philosophers-stone) -.-x|⛔️| harry-1 end subgraph azkaban-project[prisoner-of-azkaban project] azkaban(prisoner-of-azkaban) --> |requires| harry-3 end ``` /// tip | Consejo Es muy común en los paquetes de Python intentar lo mejor para **evitar romper cambios** en **nuevas versiones**, pero es mejor estar seguro e instalar nuevas versiones intencionalmente y cuando puedas ejecutar las pruebas para verificar que todo está funcionando correctamente. /// Ahora, imagina eso con **muchos** otros **paquetes** de los que dependen todos tus **proyectos**. Eso es muy difícil de manejar. Y probablemente terminarías ejecutando algunos proyectos con algunas **versiones incompatibles** de los paquetes, y sin saber por qué algo no está funcionando. Además, dependiendo de tu sistema operativo (por ejemplo, Linux, Windows, macOS), podría haber venido con Python ya instalado. Y en ese caso probablemente tenía algunos paquetes preinstalados con algunas versiones específicas **necesitadas por tu sistema**. Si instalas paquetes en el entorno global de Python, podrías terminar **rompiendo** algunos de los programas que vinieron con tu sistema operativo. ## Dónde se Instalan los Paquetes { #where-are-packages-installed } Cuando instalas Python, crea algunos directorios con algunos archivos en tu computadora. Algunos de estos directorios son los encargados de tener todos los paquetes que instalas. Cuando ejecutas:
```console // No ejecutes esto ahora, solo es un ejemplo 🤓 $ pip install "fastapi[standard]" ---> 100% ```
Eso descargará un archivo comprimido con el código de FastAPI, normalmente desde PyPI. También **descargará** archivos para otros paquetes de los que depende FastAPI. Luego, **extraerá** todos esos archivos y los pondrá en un directorio en tu computadora. Por defecto, pondrá esos archivos descargados y extraídos en el directorio que viene con tu instalación de Python, eso es el **entorno global**. ## Qué son los Entornos Virtuales { #what-are-virtual-environments } La solución a los problemas de tener todos los paquetes en el entorno global es usar un **entorno virtual para cada proyecto** en el que trabajas. Un entorno virtual es un **directorio**, muy similar al global, donde puedes instalar los paquetes para un proyecto. De esta manera, cada proyecto tendrá su propio entorno virtual (directorio `.venv`) con sus propios paquetes. ```mermaid flowchart TB subgraph stone-project[philosophers-stone project] stone(philosophers-stone) --->|requires| harry-1 subgraph venv1[.venv] harry-1[harry v1] end end subgraph azkaban-project[prisoner-of-azkaban project] azkaban(prisoner-of-azkaban) --->|requires| harry-3 subgraph venv2[.venv] harry-3[harry v3] end end stone-project ~~~ azkaban-project ``` ## Qué Significa Activar un Entorno Virtual { #what-does-activating-a-virtual-environment-mean } Cuando activas un entorno virtual, por ejemplo con: //// tab | Linux, macOS
```console $ source .venv/bin/activate ```
//// //// tab | Windows PowerShell
```console $ .venv\Scripts\Activate.ps1 ```
//// //// tab | Windows Bash O si usas Bash para Windows (por ejemplo, Git Bash):
```console $ source .venv/Scripts/activate ```
//// Ese comando creará o modificará algunas [variables de entorno](environment-variables.md){.internal-link target=_blank} que estarán disponibles para los siguientes comandos. Una de esas variables es la variable `PATH`. /// tip | Consejo Puedes aprender más sobre la variable de entorno `PATH` en la sección [Variables de Entorno](environment-variables.md#path-environment-variable){.internal-link target=_blank}. /// Activar un entorno virtual agrega su path `.venv/bin` (en Linux y macOS) o `.venv\Scripts` (en Windows) a la variable de entorno `PATH`. Digamos que antes de activar el entorno, la variable `PATH` se veía así: //// tab | Linux, macOS ```plaintext /usr/bin:/bin:/usr/sbin:/sbin ``` Eso significa que el sistema buscaría programas en: * `/usr/bin` * `/bin` * `/usr/sbin` * `/sbin` //// //// tab | Windows ```plaintext C:\Windows\System32 ``` Eso significa que el sistema buscaría programas en: * `C:\Windows\System32` //// Después de activar el entorno virtual, la variable `PATH` se vería algo así: //// tab | Linux, macOS ```plaintext /home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin ``` Eso significa que el sistema ahora comenzará a buscar primero los programas en: ```plaintext /home/user/code/awesome-project/.venv/bin ``` antes de buscar en los otros directorios. Así que, cuando escribas `python` en el terminal, el sistema encontrará el programa Python en ```plaintext /home/user/code/awesome-project/.venv/bin/python ``` y utilizará ese. //// //// tab | Windows ```plaintext C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 ``` Eso significa que el sistema ahora comenzará a buscar primero los programas en: ```plaintext C:\Users\user\code\awesome-project\.venv\Scripts ``` antes de buscar en los otros directorios. Así que, cuando escribas `python` en el terminal, el sistema encontrará el programa Python en ```plaintext C:\Users\user\code\awesome-project\.venv\Scripts\python ``` y utilizará ese. //// Un detalle importante es que pondrá el path del entorno virtual al **comienzo** de la variable `PATH`. El sistema lo encontrará **antes** que cualquier otro Python disponible. De esta manera, cuando ejecutes `python`, utilizará el Python **del entorno virtual** en lugar de cualquier otro `python` (por ejemplo, un `python` de un entorno global). Activar un entorno virtual también cambia un par de otras cosas, pero esta es una de las cosas más importantes que hace. ## Verificando un Entorno Virtual { #checking-a-virtual-environment } Cuando revisas si un entorno virtual está activo, por ejemplo con: //// tab | Linux, macOS, Windows Bash
```console $ which python /home/user/code/awesome-project/.venv/bin/python ```
//// //// tab | Windows PowerShell
```console $ Get-Command python C:\Users\user\code\awesome-project\.venv\Scripts\python ```
//// Eso significa que el programa `python` que se utilizará es el que está **en el entorno virtual**. Usas `which` en Linux y macOS y `Get-Command` en Windows PowerShell. La forma en que funciona ese comando es que irá y revisará la variable de entorno `PATH`, pasando por **cada path en orden**, buscando el programa llamado `python`. Una vez que lo encuentre, te **mostrará el path** a ese programa. La parte más importante es que cuando llamas a `python`, ese es el exacto "`python`" que será ejecutado. Así que, puedes confirmar si estás en el entorno virtual correcto. /// tip | Consejo Es fácil activar un entorno virtual, obtener un Python, y luego **ir a otro proyecto**. Y el segundo proyecto **no funcionaría** porque estás usando el **Python incorrecto**, de un entorno virtual para otro proyecto. Es útil poder revisar qué `python` se está usando. 🤓 /// ## Por qué Desactivar un Entorno Virtual { #why-deactivate-a-virtual-environment } Por ejemplo, podrías estar trabajando en un proyecto `philosophers-stone`, **activar ese entorno virtual**, instalar paquetes y trabajar con ese entorno. Y luego quieres trabajar en **otro proyecto** `prisoner-of-azkaban`. Vas a ese proyecto:
```console $ cd ~/code/prisoner-of-azkaban ```
Si no desactivas el entorno virtual para `philosophers-stone`, cuando ejecutes `python` en el terminal, intentará usar el Python de `philosophers-stone`.
```console $ cd ~/code/prisoner-of-azkaban $ python main.py // Error importando sirius, no está instalado 😱 Traceback (most recent call last): File "main.py", line 1, in import sirius ```
Pero si desactivas el entorno virtual y activas el nuevo para `prisoner-of-askaban` entonces cuando ejecutes `python` utilizará el Python del entorno virtual en `prisoner-of-azkaban`.
```console $ cd ~/code/prisoner-of-azkaban // No necesitas estar en el directorio antiguo para desactivar, puedes hacerlo donde sea que estés, incluso después de ir al otro proyecto 😎 $ deactivate // Activa el entorno virtual en prisoner-of-azkaban/.venv 🚀 $ source .venv/bin/activate // Ahora cuando ejecutes python, encontrará el paquete sirius instalado en este entorno virtual ✨ $ python main.py I solemnly swear 🐺 ```
## Alternativas { #alternatives } Esta es una guía simple para comenzar y enseñarte cómo funciona todo **por debajo**. Hay muchas **alternativas** para gestionar entornos virtuales, dependencias de paquetes (requisitos), proyectos. Una vez que estés listo y quieras usar una herramienta para **gestionar todo el proyecto**, dependencias de paquetes, entornos virtuales, etc. Te sugeriría probar uv. `uv` puede hacer muchas cosas, puede: * **Instalar Python** por ti, incluyendo diferentes versiones * Gestionar el **entorno virtual** para tus proyectos * Instalar **paquetes** * Gestionar **dependencias y versiones** de paquetes para tu proyecto * Asegurarse de que tengas un conjunto **exacto** de paquetes y versiones para instalar, incluidas sus dependencias, para que puedas estar seguro de que puedes ejecutar tu proyecto en producción exactamente igual que en tu computadora mientras desarrollas, esto se llama **locking** * Y muchas otras cosas ## Conclusión { #conclusion } Si leíste y comprendiste todo esto, ahora **sabes mucho más** sobre entornos virtuales que muchos desarrolladores por ahí. 🤓 Conocer estos detalles probablemente te será útil en el futuro cuando estés depurando algo que parece complejo, pero sabrás **cómo funciona todo por debajo**. 😎