Python y Entornos Virtuales: Instalación (venv) - Guía Completa de Producción

Introducción

Python es uno de los lenguajes de programación más populares del mundo, ampliamente utilizado para desarrollo web, ciencia de datos, aprendizaje automático, automatización y DevOps. Los entornos virtuales (venv) son esenciales para el desarrollo en Python, permitiéndote crear entornos Python aislados para diferentes proyectos con sus propias dependencias, evitando conflictos y garantizando la reproducibilidad. Esta guía completa cubre la instalación de Python, gestión de entornos virtuales y mejores prácticas de despliegue en producción.

Qué Aprenderás

  • Instalación de Python 3 en Ubuntu/Debian y CentOS/Rocky Linux
  • Gestión de múltiples versiones de Python
  • Creación y gestión de entornos virtuales con venv
  • Instalación y gestión de paquetes Python con pip
  • Gestión de requirements.txt para entornos reproducibles
  • Estrategias de despliegue en producción
  • Optimización del rendimiento
  • Mejores prácticas de seguridad
  • Solución de problemas comunes

¿Por Qué Usar Entornos Virtuales?

  • Aislamiento de Dependencias: Cada proyecto tiene sus propias dependencias
  • Control de Versiones: Diferentes proyectos pueden usar diferentes versiones de paquetes
  • Reproducibilidad: Fácil replicación de entornos
  • Sistema Limpio: Mantener el Python del sistema limpio y estable
  • Sin Problemas de Permisos: Instalar paquetes sin sudo
  • Pruebas: Probar contra diferentes versiones de Python y paquetes

Requisitos Previos

  • Ubuntu 20.04+, Debian 10+, CentOS 8+, o Rocky Linux 8+
  • Acceso root o sudo
  • Al menos 512MB de RAM
  • 2GB de espacio libre en disco
  • Conocimientos básicos de línea de comandos

Instalación

Instalar Python 3

Instalación en Ubuntu/Debian

# Actualizar lista de paquetes
sudo apt update

# Instalar Python 3 (usualmente preinstalado)
sudo apt install -y python3 python3-pip python3-venv python3-dev

# Instalar herramientas adicionales
sudo apt install -y build-essential libssl-dev libffi-dev python3-setuptools

# Verificar instalación
python3 --version
pip3 --version

# Crear alias python/pip (opcional)
echo 'alias python=python3' >> ~/.bashrc
echo 'alias pip=pip3' >> ~/.bashrc
source ~/.bashrc

Instalación en CentOS/Rocky Linux

# Actualizar sistema
sudo dnf update -y

# Instalar Python 3
sudo dnf install -y python3 python3-pip python3-devel

# Instalar herramientas de desarrollo
sudo dnf groupinstall -y "Development Tools"

# Verificar instalación
python3 --version
pip3 --version

# Crear alias
echo 'alias python=python3' >> ~/.bashrc
echo 'alias pip=pip3' >> ~/.bashrc
source ~/.bashrc

Instalar Versión Específica de Python

Usando PPA deadsnakes (Ubuntu/Debian)

# Agregar PPA deadsnakes
sudo add-apt-repository ppa:deadsnakes/ppa -y
sudo apt update

# Instalar Python 3.11
sudo apt install -y python3.11 python3.11-venv python3.11-dev

# Instalar Python 3.10
sudo apt install -y python3.10 python3.10-venv python3.10-dev

# Verificar
python3.11 --version
python3.10 --version

Usando pyenv (Todas las Distribuciones)

# Instalar dependencias
sudo apt install -y make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev \
libffi-dev liblzma-dev

# Instalar pyenv
curl https://pyenv.run | bash

# Agregar a ~/.bashrc
cat >> ~/.bashrc <<'EOF'
export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
EOF

source ~/.bashrc

# Instalar versiones de Python
pyenv install 3.11.7
pyenv install 3.10.13
pyenv install 3.9.18

# Listar versiones instaladas
pyenv versions

# Establecer versión global
pyenv global 3.11.7

# Establecer versión local para proyecto
cd /ruta/al/proyecto
pyenv local 3.10.13

Configuración

Gestión de Entornos Virtuales

Crear Entornos Virtuales

# Crear directorio del proyecto
mkdir ~/miproyecto && cd ~/miproyecto

# Crear entorno virtual
python3 -m venv venv

# Crear con versión específica de Python
python3.11 -m venv venv

# Crear con paquetes del sistema (no recomendado)
python3 -m venv venv --system-site-packages

# Verificar creación
ls -la venv/

Activar Entornos Virtuales

# Activar entorno virtual
source venv/bin/activate

# Tu prompt debería cambiar para mostrar (venv)
(venv) usuario@servidor:~/miproyecto$

# Verificar que Python es del entorno virtual
which python
# Debería mostrar: /home/usuario/miproyecto/venv/bin/python

# Verificar versión de Python
python --version

# Desactivar cuando termines
deactivate

Múltiples Entornos Virtuales

# Crear diferentes entornos para diferentes proyectos
mkdir ~/proyecto1 && cd ~/proyecto1
python3 -m venv venv

mkdir ~/proyecto2 && cd ~/proyecto2
python3 -m venv venv

# O usar diferentes nombres
mkdir ~/miaplicacion && cd ~/miaplicacion
python3 -m venv venv-dev
python3 -m venv venv-prod
python3 -m venv venv-test

Gestión de Paquetes con pip

Instalar Paquetes

# Activar entorno virtual primero
source venv/bin/activate

# Instalar paquete único
pip install requests

# Instalar versión específica
pip install Django==4.2.7

# Instalar versión mínima
pip install numpy>=1.24.0

# Instalar desde requirements.txt
pip install -r requirements.txt

# Instalar en modo editable (para desarrollo)
pip install -e .

# Instalar desde repositorio git
pip install git+https://github.com/usuario/repo.git

Gestionar Requisitos

# Listar paquetes instalados
pip list

# Mostrar detalles del paquete
pip show Django

# Generar requirements.txt
pip freeze > requirements.txt

# Generar con comentarios (mejor)
pip list --format=freeze > requirements.txt

# Crear requirements-dev.txt para dependencias de desarrollo
pip freeze > requirements-dev.txt

Actualizar Paquetes

# Actualizar paquete único
pip install --upgrade requests

# Actualizar pip mismo
pip install --upgrade pip

# Actualizar todos los paquetes (¡con cuidado!)
pip list --outdated
pip install --upgrade $(pip list --outdated --format=freeze | cut -d = -f 1)

Mejores Prácticas de Estructura de Proyecto

# Estructura recomendada de proyecto Python
miproyecto/
├── venv/                    # Entorno virtual (no en git)
├── src/                     # Código fuente
│   ├── __init__.py
│   ├── main.py
│   └── utils.py
├── tests/                   # Archivos de prueba
│   ├── __init__.py
│   └── test_main.py
├── requirements.txt         # Dependencias de producción
├── requirements-dev.txt     # Dependencias de desarrollo
├── .gitignore              # Archivo ignore de Git
├── README.md               # Documentación del proyecto
├── setup.py                # Configuración del paquete (si se distribuye)
└── .env                    # Variables de entorno (no en git)

# Crear estructura
mkdir -p miproyecto/{src,tests}
cd miproyecto
python3 -m venv venv
touch src/{__init__.py,main.py,utils.py}
touch tests/{__init__.py,test_main.py}
touch requirements.txt requirements-dev.txt .gitignore README.md .env

# Crear .gitignore
cat > .gitignore <<EOF
venv/
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
*.so
*.egg
*.egg-info/
dist/
build/
.env
.venv
*.log
EOF

Despliegue

Configuración de Despliegue en Producción

Ejemplo de Aplicación Flask

# Crear proyecto Flask
mkdir flask-app && cd flask-app
python3 -m venv venv
source venv/bin/activate

# Instalar Flask
pip install Flask gunicorn python-dotenv

# Crear estructura de aplicación
mkdir app
cat > app/__init__.py <<'EOF'
from flask import Flask

def create_app():
    app = Flask(__name__)

    @app.route('/')
    def index():
        return {'message': 'API Flask funcionando', 'status': 'healthy'}

    @app.route('/health')
    def health():
        return {'status': 'healthy'}

    return app
EOF

# Crear archivo principal de aplicación
cat > wsgi.py <<'EOF'
from app import create_app

app = create_app()

if __name__ == '__main__':
    app.run()
EOF

# Crear requirements.txt
cat > requirements.txt <<EOF
Flask==3.0.0
gunicorn==21.2.0
python-dotenv==1.0.0
EOF

# Crear archivo .env
cat > .env <<EOF
FLASK_APP=wsgi.py
FLASK_ENV=production
SECRET_KEY=tu-clave-secreta-aqui
EOF

# Probar localmente
flask run

# Ejecutar con gunicorn (producción)
gunicorn --bind 0.0.0.0:8000 --workers 4 wsgi:app

Ejemplo de Aplicación Django

# Crear proyecto Django
mkdir django-app && cd django-app
python3 -m venv venv
source venv/bin/activate

# Instalar Django
pip install Django psycopg2-binary gunicorn python-dotenv

# Crear proyecto
django-admin startproject misitio .

# Crear requirements.txt
pip freeze > requirements.txt

# Crear archivo .env
cat > .env <<EOF
DEBUG=False
SECRET_KEY=tu-clave-secreta-django
DATABASE_URL=postgresql://usuario:pass@localhost:5432/nombredb
ALLOWED_HOSTS=ejemplo.com,www.ejemplo.com
EOF

# Configurar settings.py para usar .env
pip install python-decouple

# En settings.py:
from decouple import config

SECRET_KEY = config('SECRET_KEY')
DEBUG = config('DEBUG', default=False, cast=bool)
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='').split(',')

# Ejecutar migraciones
python manage.py migrate

# Recopilar archivos estáticos
python manage.py collectstatic

# Ejecutar con gunicorn
gunicorn --bind 0.0.0.0:8000 --workers 4 misitio.wsgi:application

Configuración de Servicio Systemd

# Crear archivo de servicio systemd
sudo bash -c 'cat > /etc/systemd/system/miaplicacion.service <<EOF
[Unit]
Description=Mi Aplicación Python
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/miaplicacion
Environment="PATH=/var/www/miaplicacion/venv/bin"
EnvironmentFile=/var/www/miaplicacion/.env
ExecStart=/var/www/miaplicacion/venv/bin/gunicorn \
    --workers 4 \
    --bind 0.0.0.0:8000 \
    --timeout 120 \
    --access-logfile /var/log/miaplicacion/access.log \
    --error-logfile /var/log/miaplicacion/error.log \
    wsgi:app

Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF'

# Crear directorio de logs
sudo mkdir -p /var/log/miaplicacion
sudo chown www-data:www-data /var/log/miaplicacion

# Habilitar e iniciar servicio
sudo systemctl daemon-reload
sudo systemctl enable miaplicacion
sudo systemctl start miaplicacion
sudo systemctl status miaplicacion

Configuración de Nginx

server {
    listen 80;
    server_name ejemplo.com www.ejemplo.com;

    access_log /var/log/nginx/miaplicacion-access.log;
    error_log /var/log/nginx/miaplicacion-error.log;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect off;

        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # Archivos estáticos
    location /static/ {
        alias /var/www/miaplicacion/static/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # Archivos multimedia
    location /media/ {
        alias /var/www/miaplicacion/media/;
        expires 7d;
    }
}

Monitoreo

Estado del Entorno Virtual

# Verificar si estás en entorno virtual
echo $VIRTUAL_ENV

# Mostrar paquetes instalados
pip list

# Mostrar paquetes desactualizados
pip list --outdated

# Verificar versiones de paquetes
pip show nombre-paquete

# Verificar integridad de paquetes
pip check

Monitoreo de Aplicación

# Monitorear logs de aplicación
tail -f /var/log/miaplicacion/error.log

# Verificar estado del servicio systemd
sudo systemctl status miaplicacion

# Ver logs del servicio
sudo journalctl -u miaplicacion -f

# Verificar proceso
ps aux | grep gunicorn

# Monitorear recursos
htop

Monitoreo de Rendimiento de Python

# Instalar herramientas de monitoreo
pip install py-spy memory_profiler

# Perfilar uso de memoria
python -m memory_profiler script.py

# Perfilado de CPU con py-spy
py-spy top --pid $(pgrep -f gunicorn)

# Generar gráfico de llama
py-spy record -o profile.svg --pid $(pgrep -f gunicorn)

Solución de Problemas

Problemas de Entorno Virtual

Problema: venv no se activa

# Recrear entorno virtual
rm -rf venv
python3 -m venv venv
source venv/bin/activate

# Verificar permisos del script de activación
chmod +x venv/bin/activate

Problema: Versión incorrecta de Python en venv

# Crear con Python específico
python3.11 -m venv venv

# O usar pyenv
pyenv local 3.11.7
python -m venv venv

Problemas de Instalación de Paquetes

Problema: pip install falla

# Actualizar pip
pip install --upgrade pip setuptools wheel

# Instalar con salida detallada
pip install nombre-paquete -v

# Limpiar caché de pip
pip cache purge

# Instalar desde código fuente
pip install --no-binary :all: nombre-paquete

Problema: Permiso denegado

# Siempre usar entorno virtual
source venv/bin/activate

# Nunca usar sudo con pip en venv
# Si estás fuera de venv, usar flag --user
pip install --user nombre-paquete

Errores de Aplicación

Problema: ModuleNotFoundError

# Asegurar que el entorno virtual está activado
source venv/bin/activate

# Verificar que el paquete está instalado
pip list | grep nombre-paquete

# Reinstalar paquete
pip install --force-reinstall nombre-paquete

# Verificar PYTHONPATH
echo $PYTHONPATH

Problema: Conflictos de dependencias

# Verificar dependencias
pip check

# Mostrar árbol de dependencias
pip install pipdeptree
pipdeptree

# Crear entorno limpio
deactivate
rm -rf venv
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

Mejores Prácticas de Seguridad

Instalación Segura de Paquetes

# Siempre verificar requirements.txt antes de instalar
cat requirements.txt

# Usar modo de verificación de hash
pip install -r requirements.txt --require-hashes

# Generar hashes
pip hash nombre-paquete

# Auditar dependencias
pip install safety
safety check

# O usar pip-audit
pip install pip-audit
pip-audit

Variables de Entorno

# Nunca codificar secretos
# Usar python-dotenv
pip install python-dotenv

# Crear archivo .env
cat > .env <<EOF
SECRET_KEY=tu-clave-secreta
DATABASE_URL=postgresql://localhost/nombredb
API_KEY=tu-clave-api
EOF

# Agregar a .gitignore
echo ".env" >> .gitignore

# En código Python
from dotenv import load_dotenv
import os

load_dotenv()
secreto = os.getenv('SECRET_KEY')

Asegurar Entorno Virtual

# Establecer permisos apropiados
chmod 750 venv
chmod 640 venv/pyvenv.cfg

# Remover permisos de lectura mundial
find venv -type d -exec chmod 750 {} \;
find venv -type f -exec chmod 640 {} \;

# Hacer scripts ejecutables
chmod 750 venv/bin/*

Optimización de Rendimiento

Requisitos Optimizados

# Separar dependencias de producción y desarrollo
cat > requirements.txt <<EOF
# Solo dependencias de producción
Flask==3.0.0
gunicorn==21.2.0
psycopg2-binary==2.9.9
EOF

cat > requirements-dev.txt <<EOF
# Dependencias de desarrollo
-r requirements.txt
pytest==7.4.3
black==23.12.0
flake8==6.1.0
mypy==1.7.1
EOF

# Instalar según corresponda
pip install -r requirements.txt  # Producción
pip install -r requirements-dev.txt  # Desarrollo

Optimización de Python

# Usar __slots__ para optimización de memoria
class MiClase:
    __slots__ = ['attr1', 'attr2']

    def __init__(self, attr1, attr2):
        self.attr1 = attr1
        self.attr2 = attr2

# Usar generadores para conjuntos de datos grandes
def leer_archivo_grande(ruta_archivo):
    with open(ruta_archivo) as f:
        for linea in f:
            yield linea.strip()

# Usar comprensiones de lista
resultado = [x * 2 for x in range(1000)]

# Cachear operaciones costosas
from functools import lru_cache

@lru_cache(maxsize=128)
def funcion_costosa(n):
    # Cómputo costoso
    return resultado

Optimización de Gunicorn

# Workers óptimos = (2 x núcleos de CPU) + 1
gunicorn --workers 5 \
         --worker-class sync \
         --worker-connections 1000 \
         --timeout 30 \
         --keep-alive 5 \
         --bind 0.0.0.0:8000 \
         wsgi:app

# Para aplicaciones asíncronas
gunicorn --workers 5 \
         --worker-class uvicorn.workers.UvicornWorker \
         --bind 0.0.0.0:8000 \
         main:app

Conclusión

Has configurado exitosamente Python con entornos virtuales para desarrollo y producción. Este enfoque aislado y reproducible garantiza una gestión limpia de dependencias y un despliegue profesional de aplicaciones Python.

Puntos Clave

  • Los entornos virtuales aíslan las dependencias del proyecto
  • Usar requirements.txt para entornos reproducibles
  • Separar dependencias de producción y desarrollo
  • Nunca instalar paquetes con sudo dentro de venv
  • Usar variables de entorno para configuración sensible
  • gunicorn + systemd proporciona despliegue listo para producción

Mejores Prácticas

  1. Siempre usar entornos virtuales
  2. Mantener requirements.txt actualizado
  3. Usar versiones específicas de paquetes en producción
  4. Implementar auditorías de seguridad regularmente
  5. Monitorear rendimiento de aplicación
  6. Usar gestores de procesos (systemd, supervisor)
  7. Mantener Python y paquetes actualizados

Próximos Pasos

  1. Configurar pruebas automatizadas (pytest)
  2. Implementar pipelines de CI/CD
  3. Configurar monitoreo y alertas
  4. Configurar respaldos automáticos
  5. Implementar agregación de logs
  6. Crear procedimientos de recuperación ante desastres

¡Los entornos virtuales de Python son fundamentales para el desarrollo profesional en Python. Domínalos para aplicaciones limpias, mantenibles y listas para producción!

¡Feliz codificación!