Python

Entornos virtuales y dependencias: cada proyecto en su propia burbuja

Aprende a usar entornos virtuales en Python para aislar dependencias, trabajar con venv y pip, registrar paquetes con requirements.txt y reconstruir proyectos de forma reproducible.

☰ Contenido de la guía ⌄
El problema

El problema: todos los proyectos comparten la misma habitación

Instalar una biblioteca en Python parece sencillo: ejecutamos un comando, comenzamos a importarla y seguimos programando. El problema aparece cuando nuestra computadora deja de tener un solo proyecto.

Imagina que estás trabajando en dos aplicaciones completamente independientes. Una es un proyecto web y la otra procesa datos.

Proyecto web

Tiene su propio código, su propio ritmo de actualización y sus propias dependencias.

Proyecto de datos

También necesita bibliotecas de Python, pero no necesariamente las mismas versiones que el proyecto web.

Mientras ambos utilizan exactamente las mismas versiones puede parecer que no existe ningún problema. Pero ahora supongamos que los dos necesitan una misma biblioteca y cada uno depende de una versión diferente.

Proyecto web Necesita:
paquete 1.x
Proyecto de datos Necesita:
paquete 2.x
La pregunta

Si ambos proyectos utilizan el mismo espacio de paquetes de Python, ¿qué versión dejamos instalada?

Para entender el conflicto, pensemos primero en una instalación de Python donde todos nuestros proyectos terminan utilizando el mismo conjunto de paquetes instalados.

Python │ ├── biblioteca A ├── biblioteca B ├── biblioteca C └── paquete X ↑ │ ├── Proyecto web ├── Proyecto de datos └── Otro proyecto

En este modelo, los proyectos no poseen realmente sus propias dependencias. Todos miran hacia un mismo espacio compartido.

Proyecto A
↓
Python compartido
↓
mismos paquetes

Eso significa que una decisión aparentemente local puede afectar a otros proyectos. Actualizar una biblioteca para solucionar un problema en una aplicación puede introducir un cambio incompatible en otra.

El detalle importante

El problema no es que Python permita instalar paquetes. El problema es hacer que proyectos independientes dependan accidentalmente del mismo conjunto mutable de paquetes.

Veamos el conflicto de una forma más concreta.

Proyecto A

Fue creado y probado utilizando:

paquete 1.x
Proyecto B

Utiliza una funcionalidad disponible en:

paquete 2.x

Si instalamos la versión nueva para satisfacer al Proyecto B, podríamos modificar el entorno sobre el que depende el Proyecto A.

Una sola instalación compartida ¿paquete 1.x o paquete 2.x?

Podríamos intentar mantener siempre todos nuestros proyectos sincronizados, pero esa estrategia se vuelve frágil conforme crecen la cantidad de aplicaciones y dependencias.

La alternativa es cambiar la pregunta.

En lugar de preguntar

“¿Qué versión de esta biblioteca debe tener mi computadora?”, preguntaremos: “¿Qué versión necesita este proyecto?”

Proyecto A → su entorno · Proyecto B → su entorno

Esa separación es precisamente la idea detrás de los entornos virtuales de Python: permitir que cada proyecto mantenga su propio contexto de dependencias sin obligar a los demás a tomar las mismas decisiones.

Comparación entre proyectos Python que comparten dependencias y proyectos aislados con sus propios entornos virtuales.
Sin entornos virtuales, varios proyectos pueden competir por las mismas dependencias. Con un entorno por proyecto, cada uno mantiene sus propias versiones de forma aislada.
El concepto

Qué es realmente un entorno virtual

Un entorno virtual es un contexto de Python asociado a un proyecto, con su propio intérprete y su propia ubicación para instalar paquetes.

La idea es sencilla: en lugar de hacer que todos nuestros proyectos dependan del mismo conjunto de bibliotecas instaladas, cada proyecto puede mantener las suyas por separado.

proyecto
↓
entorno virtual
↓
sus dependencias

Podemos imaginarlo como una burbuja alrededor de las herramientas Python que necesita ese proyecto.

Modelo mental

El entorno virtual no intenta aislar toda la computadora. Su objetivo es aislar el contexto Python utilizado por el proyecto.

La palabra virtual puede hacer pensar que estamos creando una computadora completa dentro de otra, pero un entorno virtual de Python es mucho más pequeño y específico.

Sí separa

El intérprete utilizado por el proyecto, los ejecutables asociados al entorno y el lugar donde se instalan sus paquetes Python.

No separa

El sistema operativo, la CPU, la memoria RAM, la red ni todos los procesos de la computadora.

Paquetes Python
Cada entorno puede tener versiones diferentes.
Intérprete
El proyecto puede apuntar al Python contenido en su entorno.
Sistema operativo
Sigue siendo el mismo.
Hardware
También sigue siendo compartido.
No confundir

Un entorno virtual de Python no cumple el mismo propósito que Docker ni que una máquina virtual. Aquí nos interesa aislar principalmente Python y sus dependencias.

Normalmente guardaremos el entorno dentro del propio directorio del proyecto utilizando una carpeta llamada .venv.

mi_proyecto/ │ ├── .venv/ │ ├── intérprete de Python │ ├── pip │ └── paquetes instalados │ └── programa.py

Dentro de .venv Python crea la estructura necesaria para que ese proyecto disponga de su propio contexto.

Python

El entorno contiene un intérprete asociado a esa instalación de Python.

pip

Permite instalar paquetes dentro de ese entorno.

Paquetes

Las dependencias del proyecto viven separadas de otros entornos.

Código

Nuestro código permanece fuera de .venv.

Una distinción útil

.venv contiene el entorno. Nuestro código sigue perteneciendo al proyecto.

Crear el entorno

Crear la burbuja de un proyecto

Python incluye el módulo venv, que puede crear un entorno virtual sin instalar una herramienta adicional.

El comando que utilizaremos es:

python -m venv .venv

Aunque al principio parece una instrucción para memorizar, cada parte tiene un significado concreto.

python
↓
-m
↓
venv
↓
.venv
python

Es el intérprete con el que vamos a crear el entorno.

-m

Le indica a Python que ejecute un módulo.

venv

Es el módulo de la biblioteca estándar encargado de crear el entorno.

.venv

Es el directorio donde queremos guardar ese entorno.

Observa algo importante

El entorno se crea utilizando una instalación de Python existente. No estamos descargando un sistema operativo ni construyendo una máquina virtual completa.

PowerShell
# Dentro de la carpeta del proyecto

python -m venv .venv

# Activar el entorno en PowerShell
.\.venv\Scripts\Activate.ps1
Bash
# Dentro de la carpeta del proyecto

python3 -m venv .venv

# Activar el entorno
source .venv/bin/activate

El nombre .venv es una convención, no una palabra reservada de Python.

Podríamos crear exactamente el mismo tipo de entorno utilizando otros nombres:

.venv venv env entorno

Por ejemplo:

python -m venv entorno

crearía el entorno dentro de una carpeta llamada entorno.

Convención recomendada

En esta guía utilizaremos .venv porque comunica claramente su propósito, mantiene el entorno dentro del proyecto y es una convención fácil de reconocer en editores y herramientas.

Nuestro proyecto empieza entonces a verse así:

mi_proyecto/ │ ├── .venv/ │ ├── programa.py │ └── otros_archivos.py

Pero todavía queda una pregunta importante: ¿qué hay realmente dentro de esa burbuja y qué pertenece al proyecto?

Proyecto Python con el código separado de una carpeta .venv que contiene el intérprete, pip y los paquetes instalados.
El entorno virtual vive dentro del proyecto, pero mantiene separados el intérprete, pip y las dependencias del código fuente.
Activar el entorno

Qué cambia cuando activas un entorno

Crear .venv y activarlo son dos operaciones diferentes. La primera construye el entorno; la segunda hace que nuestra terminal empiece a utilizarlo de forma cómoda.

Cuando activamos un entorno virtual no estamos “encendiendo” una máquina separada. Lo que ocurre principalmente es que la sesión de la terminal modifica la forma en que busca ejecutables.

terminal
↓
.venv
↓
Python
Idea clave

Activar el entorno hace que comandos como python y pip puedan resolverse primero hacia los ejecutables contenidos en .venv.

Podemos imaginar el cambio como una modificación en el camino que sigue la terminal cuando escribimos python.

Antes de activar
python
↓
Python global
Después de activar
python
↓
.venv / Python

Muchos shells también modifican el indicador de la terminal para mostrar algo parecido a:

(.venv) usuario@equipo:~/mi_proyecto$

Esa marca es útil, pero no debería ser nuestra única prueba de que estamos utilizando el intérprete correcto.

PowerShell
# Windows / PowerShell

where.exe python

python -c "import sys; print(sys.executable)"
Bash
# Linux / macOS

command -v python

python -c "import sys; print(sys.executable)"

El segundo comando es especialmente útil porque no depende de interpretar visualmente el prompt de la terminal.

python -c "import sys; print(sys.executable)"

Python nos responde directamente con la ruta del intérprete que está ejecutando el comando.

Sin el entorno

La ruta apuntará normalmente a una instalación de Python disponible en el sistema.

Con el entorno activo

La ruta debería apuntar al intérprete ubicado dentro de .venv.

Regla práctica

Si tienes dudas sobre qué entorno estás utilizando, no adivines: pregúntale a Python cuál es su ejecutable con sys.executable.

Hay un detalle que ayuda a entender todavía mejor qué significa activar un entorno: no es obligatorio activarlo para utilizarlo.

Podemos ejecutar directamente el intérprete que está dentro de .venv.

Windows

.venv\Scripts\python.exe

Linux / macOS

.venv/bin/python

activar
↓
comodidad en la terminal
Entonces, ¿para qué activamos?

Principalmente para no tener que escribir la ruta completa del intérprete cada vez. La activación prepara la sesión de la terminal para que podamos trabajar cómodamente con ese entorno.

Instalar dependencias

pip y el problema del paquete equivocado

Ya sabemos comprobar qué Python estamos utilizando. Ahora aparece una pregunta igual de importante: cuando instalamos una biblioteca, ¿en qué Python la estamos instalando?

Es común encontrar instrucciones como:

pip install requests

El comando puede funcionar perfectamente, pero todavía existe una pregunta que no deberíamos ignorar:

La pregunta correcta

¿Ese pip pertenece al mismo Python con el que vamos a ejecutar nuestro proyecto?

Si nuestra computadora tiene varias instalaciones de Python, varios entornos virtuales o configuraciones diferentes del PATH, asumirlo puede llevarnos a instalar el paquete en un lugar y ejecutar el programa desde otro.

Bash
# Forma explícita que utilizaremos en esta guía
python -m pip install requests

# También puede funcionar, pero depende de qué pip resuelva la terminal
pip install requests

La forma python -m pip hace explícita una relación muy importante.

elegimos Python
↓
ese Python ejecuta pip
↓
paquete en ese entorno

La opción -m le pide al intérprete que ejecute el módulo pip. De esa forma primero decidimos qué Python utilizar y después dejamos que ese mismo Python gestione sus paquetes.

Patrón recomendado

En esta guía preferiremos python -m pip porque hace visible la relación entre el intérprete y el gestor de paquetes.

No significa que pip esté mal

Ejecutar simplemente pip es válido cuando sabemos exactamente qué ejecutable está resolviendo nuestra terminal. La forma con python -m pip reduce esa ambigüedad.

Podemos verificar la relación entre Python y pip con un comando muy sencillo:

python -m pip --version

La salida suele mostrar tres piezas de información útiles:

Versión de pip

Nos indica qué versión del gestor está ejecutándose.

Ruta

Permite comprobar dónde está instalado.

Python asociado

Nos ayuda a confirmar qué instalación está gestionando esos paquetes.

.venv

Si estamos dentro del entorno correcto, esperamos reconocerlo en la ruta.

Podemos combinar esta comprobación con la que ya conocemos:

python -c "import sys; print(sys.executable)" python -m pip --version
Lo que queremos comprobar

Tanto el intérprete como el lugar donde pip gestiona paquetes deberían corresponder al entorno virtual de nuestro proyecto.

Llegados a este punto ya podemos visualizar una cadena completa: el proyecto selecciona un Python, ese Python ejecuta pip y pip instala las dependencias dentro de ese entorno.

Proyecto Python usando el intérprete y pip de su entorno .venv para instalar las dependencias dentro del entorno, frente a una instalación incorrecta fuera de él.
Usar el Python del entorno para ejecutar pip mantiene las dependencias dentro de .venv y evita instalarlas accidentalmente en otro Python.
Qué estamos instalando

Dependencias directas y dependencias transitivas

Cuando instalamos una biblioteca, el entorno puede terminar conteniendo más paquetes de los que nosotros elegimos conscientemente.

Supongamos que nuestro proyecto necesita una biblioteca llamada paquete-web.

nuestro proyecto
↓
paquete-web
↓
otros paquetes

Nosotros decidimos utilizar paquete-web, pero esa biblioteca también puede necesitar otras para funcionar.

Idea importante

Una dependencia puede tener sus propias dependencias. Por eso un único comando de instalación puede añadir varios paquetes al entorno.

Dependencia directa

Es una biblioteca que nuestro proyecto decide utilizar directamente.

Dependencia transitiva

Es una biblioteca que otra dependencia necesita para poder funcionar.

Podemos imaginarlo así:

nuestro proyecto │ └── paquete-web │ ├── dependencia A ├── dependencia B └── dependencia C

Desde la perspectiva de nuestro proyecto, paquete-web es una dependencia directa. Las otras aparecen indirectamente porque paquete-web las necesita.

Consecuencia

El contenido de un entorno virtual puede ser bastante mayor que la lista de bibliotecas que recordamos haber instalado manualmente.

Bash
# Instalar una dependencia directa
python -m pip install requests

# Ver todos los paquetes presentes en el entorno
python -m pip list
Registrar el entorno

Cómo registrar las dependencias de un proyecto

Un entorno virtual resuelve el aislamiento local, pero todavía necesitamos responder otra pregunta: ¿cómo sabrá otra persona qué debe instalar para reconstruir nuestro proyecto?

La carpeta .venv contiene los paquetes instalados en nuestra computadora, pero no queremos depender de esa carpeta para siempre.

entorno funcionando
↓
lista de dependencias
↓
entorno reconstruible

Una de las formas más sencillas y extendidas de registrar ese estado en proyectos Python es mediante un archivo:

requirements.txt
Bash
# Guardar los paquetes instalados y sus versiones
python -m pip freeze > requirements.txt

Estás viendo solo el 60% del contenido. Hazte Premium para acceder a la guía completa.

Comunidad

Comentarios y valoraciones

No hay comentarios aún. ¡Sé el primero en opinar!