Flask
Tutorial Flask: Variables de entorno
Aprende a gestionar variables de entorno en Flask usando python-dotenv para configurar entornos seguros y flexibles en tus aplicaciones Python.
Aprende Flask y certifícatepython-dotenv en Flask
La gestión de variables de entorno en aplicaciones Flask requiere herramientas específicas que faciliten su carga y uso durante el desarrollo. La librería python-dotenv se ha convertido en el estándar para esta tarea, permitiendo cargar automáticamente variables desde archivos .env
sin necesidad de configurarlas manualmente en el sistema operativo.
Esta librería resulta especialmente útil en entornos de desarrollo donde necesitamos cambiar frecuentemente configuraciones como URLs de bases de datos, claves API o configuraciones de depuración. En lugar de modificar variables del sistema cada vez, podemos mantener todas las configuraciones en un archivo que se carga automáticamente al iniciar la aplicación.
Instalación y configuración básica
Para integrar python-dotenv en nuestro proyecto Flask, primero debemos instalar la librería:
pip install python-dotenv
Una vez instalada, podemos crear un archivo .env
en la raíz del proyecto con nuestras variables de configuración:
FLASK_ENV=development
DATABASE_URL=mysql://usuario:password@localhost/mi_base_datos
SECRET_KEY=mi_clave_secreta_super_segura
DEBUG=True
API_KEY=sk-1234567890abcdef
Para cargar estas variables en nuestra aplicación Flask, utilizamos la función load_dotenv()
al inicio de nuestro archivo principal:
from flask import Flask
from dotenv import load_dotenv
import os
# Cargar variables de entorno desde .env
load_dotenv()
app = Flask(__name__)
# Acceder a las variables cargadas
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY')
app.config['DEBUG'] = os.getenv('DEBUG', 'False').lower() == 'true'
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL')
@app.route('/')
def home():
api_key = os.getenv('API_KEY')
return f"Aplicación configurada con API Key: {api_key[:10]}..."
Configuración avanzada con diferentes entornos
En proyectos profesionales es común tener múltiples entornos (desarrollo, pruebas, producción) con configuraciones diferentes. Python-dotenv permite manejar esta situación mediante archivos específicos para cada entorno:
from flask import Flask
from dotenv import load_dotenv
import os
def create_app():
app = Flask(__name__)
# Determinar el entorno actual
env = os.getenv('FLASK_ENV', 'development')
# Cargar archivo .env específico del entorno
if env == 'development':
load_dotenv('.env.development')
elif env == 'testing':
load_dotenv('.env.testing')
elif env == 'production':
load_dotenv('.env.production')
else:
load_dotenv() # Archivo .env por defecto
# Configurar la aplicación
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY')
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
return app
app = create_app()
Para este enfoque, crearíamos archivos separados como .env.development
, .env.testing
y .env.production
, cada uno con las configuraciones específicas de su entorno correspondiente.
Integración con configuraciones de Flask
Una práctica recomendada es centralizar toda la configuración en una clase de configuración que utilice las variables cargadas por python-dotenv:
import os
from dotenv import load_dotenv
# Cargar variables antes de definir la configuración
load_dotenv()
class Config:
SECRET_KEY = os.getenv('SECRET_KEY') or 'clave-por-defecto-desarrollo'
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL') or 'sqlite:///app.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
# Configuraciones específicas de la aplicación
MAIL_SERVER = os.getenv('MAIL_SERVER')
MAIL_PORT = int(os.getenv('MAIL_PORT', 587))
MAIL_USE_TLS = os.getenv('MAIL_USE_TLS', 'True').lower() == 'true'
# Configuraciones de APIs externas
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
STRIPE_PUBLIC_KEY = os.getenv('STRIPE_PUBLIC_KEY')
STRIPE_SECRET_KEY = os.getenv('STRIPE_SECRET_KEY')
class DevelopmentConfig(Config):
DEBUG = True
SQLALCHEMY_DATABASE_URI = os.getenv('DEV_DATABASE_URL') or 'sqlite:///dev.db'
class ProductionConfig(Config):
DEBUG = False
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL')
# Diccionario de configuraciones disponibles
config = {
'development': DevelopmentConfig,
'production': ProductionConfig,
'default': DevelopmentConfig
}
Luego, en nuestro archivo principal de la aplicación:
from flask import Flask
from config import config
def create_app(config_name='default'):
app = Flask(__name__)
app.config.from_object(config[config_name])
# Verificar que las variables críticas estén configuradas
if not app.config.get('SECRET_KEY'):
raise ValueError("SECRET_KEY no está configurada")
return app
# Crear la aplicación con la configuración del entorno
env = os.getenv('FLASK_ENV', 'development')
app = create_app(env)
Validación y valores por defecto
Python-dotenv permite implementar validaciones robustas para asegurar que todas las variables necesarias estén presentes y tengan valores válidos:
import os
from dotenv import load_dotenv
load_dotenv()
def validate_environment():
"""Valida que todas las variables de entorno requeridas estén presentes"""
required_vars = [
'SECRET_KEY',
'DATABASE_URL',
'OPENAI_API_KEY'
]
missing_vars = []
for var in required_vars:
if not os.getenv(var):
missing_vars.append(var)
if missing_vars:
raise EnvironmentError(
f"Variables de entorno faltantes: {', '.join(missing_vars)}"
)
def get_database_config():
"""Obtiene configuración de base de datos con validación"""
db_url = os.getenv('DATABASE_URL')
if not db_url:
raise ValueError("DATABASE_URL es requerida")
# Validar formato de URL de base de datos
if not db_url.startswith(('mysql://', 'postgresql://', 'sqlite:///')):
raise ValueError("DATABASE_URL debe tener un formato válido")
return db_url
# Usar las funciones de validación
try:
validate_environment()
database_uri = get_database_config()
print("Configuración validada correctamente")
except (EnvironmentError, ValueError) as e:
print(f"Error de configuración: {e}")
exit(1)
Mejores prácticas de seguridad
Al trabajar con python-dotenv, es fundamental seguir prácticas de seguridad específicas para proteger información sensible:
Exclusión del control de versiones:
# Archivo .gitignore
.env
.env.local
.env.development
.env.testing
.env.production
*.env
Archivo de ejemplo para el equipo:
# Archivo .env.example (SÍ incluir en el repositorio)
FLASK_ENV=development
DATABASE_URL=mysql://usuario:password@localhost/nombre_base_datos
SECRET_KEY=tu_clave_secreta_aqui
DEBUG=True
API_KEY=tu_api_key_aqui
MAIL_SERVER=smtp.gmail.com
MAIL_PORT=587
MAIL_USE_TLS=True
Carga condicional en producción:
import os
from dotenv import load_dotenv
# Solo cargar .env en desarrollo, no en producción
if os.getenv('FLASK_ENV') != 'production':
load_dotenv()
app = Flask(__name__)
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY')
# Verificar configuración crítica
if not app.config['SECRET_KEY']:
if os.getenv('FLASK_ENV') == 'production':
raise RuntimeError("SECRET_KEY debe estar configurada en producción")
else:
app.config['SECRET_KEY'] = 'clave-desarrollo-temporal'
Esta aproximación garantiza que las variables sensibles se gestionen correctamente en cada entorno, manteniendo la seguridad sin comprometer la facilidad de desarrollo.
Otras lecciones de Flask
Accede a todas las lecciones de Flask y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Flask
Introducción Y Entorno
Instalación Y Configuración Flask Con Venv
Introducción Y Entorno
Rutas Endpoints Rest Get
Api Rest
Respuestas Con Esquemas Flask Marshmallow
Api Rest
Rutas Endpoints Rest Post, Put Y Delete
Api Rest
Manejo De Errores Y Códigos De Estado Http
Api Rest
Ejercicios de programación de Flask
Evalúa tus conocimientos de esta lección Variables de entorno con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.