Un entorno virtual de Python (venv) es un directorio con su propio intérprete y sus propios paquetes, separado del Python del sistema. Así cada proyecto tiene sus dependencias y versiones sin interferir con otros proyectos ni con las herramientas de Ubuntu que dependen de Python. En este tutorial instalarás Python 3 en Ubuntu 24.04, crearás un entorno virtual, gestionarás dependencias con pip y requirements.txt y, al final, ejecutarás una pequeña aplicación Flask con Gunicorn como servicio de systemd usando ese entorno.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
- Un usuario no root con privilegios
sudo. - Conocimientos básicos de la línea de comandos.
Paso 1: Instalar Python 3, pip y venv
Ubuntu 24.04 incluye Python 3.12 como python3, pero el módulo venv y pip vienen en paquetes aparte. Actualiza el índice de paquetes e instálalos:
sudo apt update
sudo apt install python3 python3-venv python3-pip
Si vas a instalar paquetes que compilan extensiones en C (por ejemplo psycopg2 sin binarios, o mysqlclient), añade también las cabeceras y el compilador:
sudo apt install python3-dev build-essential
Comprueba las versiones instaladas:
python3 --version
python3 -m pip --version
Python 3.12.3
pip 24.0 from /usr/lib/python3/dist-packages/pip (python 3.12)
Notaen Ubuntu 24.04 no existe el comando
python, solopython3. Dentro de un entorno virtual activado sí podrás usarpythonypipdirectamente.
Paso 2: Entender por qué pip no instala paquetes en el sistema
Ubuntu 24.04 aplica el PEP 668: el Python del sistema está marcado como gestionado externamente, de modo que pip se niega a instalar paquetes fuera de un entorno virtual para no romper las herramientas del sistema. Puedes comprobarlo:
python3 -m pip install requests
error: externally-managed-environment
This environment is externally managed
To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.
Tienes tres opciones correctas:
| Necesidad | Solución |
|---|---|
| Dependencias de un proyecto | Un entorno virtual con python3 -m venv (este tutorial) |
Una herramienta de línea de comandos (por ejemplo httpie o black) | pipx, que crea un entorno aislado por herramienta |
| Una librería que usan scripts del sistema | El paquete de apt, como python3-requests |
No uses --break-system-packages ni sudo pip install: pueden sobrescribir módulos de los que depende el propio Ubuntu.
Paso 3: Crear y activar un entorno virtual
Crea un directorio para el proyecto y, dentro de él, un entorno virtual llamado .venv. Este nombre es una convención que reconocen la mayoría de editores y herramientas:
mkdir ~/miproyecto
cd ~/miproyecto
python3 -m venv .venv
El comando crea .venv/ con un intérprete enlazado al del sistema, su propio pip y un directorio site-packages vacío. Activa el entorno:
source .venv/bin/activate
El prompt muestra ahora el nombre del entorno. Comprueba que python y pip apuntan al entorno y no al sistema:
which python
pip --version
/home/your_user/miproyecto/.venv/bin/python
pip 24.0 from /home/your_user/miproyecto/.venv/lib/python3.12/site-packages/pip (python 3.12)
Actualiza pip dentro del entorno. Esto solo afecta a este proyecto:
python -m pip install --upgrade pip
Para salir del entorno usa deactivate. No hace falta tenerlo activado para usarlo: basta con llamar a los binarios por su ruta, por ejemplo ~/miproyecto/.venv/bin/python. Eso es lo que harás más adelante en el servicio de systemd.
Paso 4: Instalar paquetes y fijar las dependencias
Con el entorno activado, instala los paquetes del proyecto. Para el ejemplo final necesitas Flask y Gunicorn:
pip install flask gunicorn
Lista lo instalado y comprueba que no hay dependencias rotas:
pip list
pip check
No broken requirements found.
Guarda las versiones exactas en requirements.txt. Este archivo se versiona junto al código para reproducir el mismo entorno en otro servidor:
pip freeze > requirements.txt
cat requirements.txt
blinker==1.9.0
click==8.2.1
Flask==3.1.2
gunicorn==23.0.0
itsdangerous==2.2.0
Jinja2==3.1.6
MarkupSafe==3.0.2
packaging==25.0
Werkzeug==3.1.3
Las versiones que veas serán las más recientes en el momento de instalar.
El directorio .venv no se versiona: depende de la ruta y del intérprete de cada máquina. Si usas Git, exclúyelo:
echo ".venv/" >> .gitignore
Para reconstruir el entorno en otra máquina, o desde cero si se corrompe, borra el directorio y reinstala desde el archivo:
deactivate
rm -rf .venv
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
Si quieres separar las herramientas de desarrollo (pytest, linters) de las de producción, crea un requirements-dev.txt que empiece con la línea -r requirements.txt y añada el resto. En producción instalas solo requirements.txt.
Paso 5: Usar otra versión de Python (opcional)
Un entorno virtual usa la versión del intérprete con que lo creas. Si tu proyecto necesita una versión distinta de la 3.12 del sistema, el PPA deadsnakes publica otras versiones para Ubuntu LTS que se instalan junto a la del sistema sin reemplazarla:
sudo apt install software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update
sudo apt install python3.13 python3.13-venv
Crea el entorno con ese intérprete concreto:
python3.13 -m venv .venv
.venv/bin/python --version
Python 3.13.7
Advertencianunca cambies el enlace
/usr/bin/python3ni usesupdate-alternativespara apuntarlo a otra versión. Muchas herramientas de Ubuntu, comoaptyadd-apt-repository, dependen de la 3.12.
Paso 6: Ejecutar una aplicación en producción con el entorno virtual
En producción el entorno virtual no se activa: el servicio llama directamente a los binarios de .venv/bin. Vas a desplegar una aplicación Flask mínima en /srv/miapp, ejecutada por un usuario sin privilegios.
Crea el usuario de sistema y el directorio de la aplicación:
sudo useradd --system --home-dir /srv/miapp --shell /usr/sbin/nologin miapp
sudo mkdir -p /srv/miapp
sudo chown miapp:miapp /srv/miapp
Crea el archivo de la aplicación:
sudo -u miapp nano /srv/miapp/app.py
from flask import Flask
app = Flask(__name__)
@app.get("/")
def index():
return {"status": "ok"}
Crea el entorno virtual como el usuario miapp e instala las dependencias. Si has copiado tu requirements.txt a /srv/miapp, usa -r requirements.txt en lugar de nombrar los paquetes:
sudo -u miapp python3 -m venv /srv/miapp/.venv
sudo -u miapp /srv/miapp/.venv/bin/pip install flask gunicorn
Crea la unidad de systemd:
sudo nano /etc/systemd/system/miapp.service
[Unit]
Description=Aplicación Flask miapp (Gunicorn)
After=network.target
[Service]
User=miapp
Group=miapp
WorkingDirectory=/srv/miapp
ExecStart=/srv/miapp/.venv/bin/gunicorn --workers 3 --bind 127.0.0.1:8000 app:app
Restart=on-failure
[Install]
WantedBy=multi-user.target
app:app significa "el objeto app del módulo app.py". Gunicorn escucha solo en 127.0.0.1, porque lo habitual es poner delante un proxy inverso como Nginx. Una regla orientativa para --workers es dos por núcleo de CPU más uno.
Carga la unidad, habilítala y arráncala:
sudo systemctl daemon-reload
sudo systemctl enable --now miapp
sudo systemctl status miapp
● miapp.service - Aplicación Flask miapp (Gunicorn)
Loaded: loaded (/etc/systemd/system/miapp.service; enabled; preset: enabled)
Active: active (running) since Thu 2026-09-25 10:20:14 UTC; 3s ago
Comprueba que responde:
curl http://127.0.0.1:8000/
{"status":"ok"}
Para actualizar dependencias más adelante, instala el nuevo requirements.txt con el pip del entorno y reinicia el servicio:
sudo -u miapp /srv/miapp/.venv/bin/pip install -r /srv/miapp/requirements.txt
sudo systemctl restart miapp
Solución de problemas
The virtual environment was not created successfully because ensurepip is not available. Falta el paquete venv de esa versión de Python. Instala python3-venv (o python3.13-venv si usas deadsnakes) y vuelve a crear el entorno.
ModuleNotFoundError al ejecutar la aplicación. El paquete está instalado en otro entorno o en ninguno. Comprueba qué intérprete se usa con which python y lista los paquetes con pip list desde ese mismo entorno. En systemd, revisa que ExecStart apunte a .venv/bin/ y no a /usr/bin/.
El entorno deja de funcionar tras mover el directorio del proyecto. Los scripts de .venv/bin contienen rutas absolutas. No muevas ni copies un entorno virtual: bórralo y créalo de nuevo en la ruta nueva con pip install -r requirements.txt.
El entorno se rompe tras actualizar Ubuntu a otra versión. Si cambia la versión menor de Python (por ejemplo de 3.12 a 3.13), el enlace del entorno apunta a un intérprete que ya no existe. Recrea el entorno igual que en el caso anterior.
El servicio no arranca. Consulta el error de Gunicorn en el journal:
sudo journalctl -u miapp -n 50 --no-pager
Conclusión
Has instalado Python 3 en Ubuntu 24.04, has creado un entorno virtual aislado, has fijado sus dependencias en requirements.txt y has ejecutado una aplicación con Gunicorn y systemd usando el intérprete del entorno sin activarlo. Como siguientes pasos puedes poner Nginx como proxy inverso delante de Gunicorn con un certificado TLS de Let's Encrypt, auditar las dependencias con pip-audit y automatizar el despliegue desde tu repositorio.
