import os
from typing import Optional, TypeVar, Type, Union, List
from pathlib import Path
T = TypeVar('T', str, int, float, bool)
class EnvLoader:
"""Load and validate environment variables with type conversion."""
@staticmethod
def get_str(key: str, default: Optional[str] = None, required: bool = False) -> Optional[str]:
"""Get string environment variable."""
value = os.getenv(key, default)
if required and value is None:
raise ValueError(f"Required environment variable '{key}' is not set")
return value
@staticmethod
def get_int(key: str, default: Optional[int] = None, required: bool = False) -> Optional[int]:
"""Get integer environment variable."""
value = os.getenv(key)
if value is None:
if required:
raise ValueError(f"Required environment variable '{key}' is not set")
return default
try:
return int(value)
except ValueError:
raise ValueError(f"Environment variable '{key}' must be an integer, got '{value}'")
@staticmethod
def get_float(key: str, default: Optional[float] = None, required: bool = False) -> Optional[float]:
"""Get float environment variable."""
value = os.getenv(key)
if value is None:
if required:
raise ValueError(f"Required environment variable '{key}' is not set")
return default
try:
return float(value)
except ValueError:
raise ValueError(f"Environment variable '{key}' must be a float, got '{value}'")
@staticmethod
def get_bool(key: str, default: Optional[bool] = None, required: bool = False) -> Optional[bool]:
"""Get boolean environment variable."""
value = os.getenv(key)
if value is None:
if required:
raise ValueError(f"Required environment variable '{key}' is not set")
return default
if value.lower() in ('true', '1', 'yes', 'on'):
return True
elif value.lower() in ('false', '0', 'no', 'off'):
return False
else:
raise ValueError(f"Environment variable '{key}' must be a boolean, got '{value}'")
@staticmethod
def get_list(key: str, separator: str = ',', default: Optional[List[str]] = None,
required: bool = False) -> Optional[List[str]]:
"""Get list environment variable."""
value = os.getenv(key)
if value is None:
if required:
raise ValueError(f"Required environment variable '{key}' is not set")
return default or []
return [item.strip() for item in value.split(separator) if item.strip()]
@staticmethod
def get_path(key: str, default: Optional[Path] = None, required: bool = False) -> Optional[Path]:
"""Get path environment variable."""
value = os.getenv(key)
if value is None:
if required:
raise ValueError(f"Required environment variable '{key}' is not set")
return default
path = Path(value)
if not path.exists():
raise ValueError(f"Path in environment variable '{key}' does not exist: {path}")
return path
# Example usage
if __name__ == "__main__":
# Example configuration class
class Config:
# Database settings
DB_HOST = EnvLoader.get_str('DB_HOST', 'localhost')
DB_PORT = EnvLoader.get_int('DB_PORT', 5432)
DB_NAME = EnvLoader.get_str('DB_NAME', required=True)
# API settings
API_KEY = EnvLoader.get_str('API_KEY', required=True)
DEBUG = EnvLoader.get_bool('DEBUG', False)
RETRY_COUNT = EnvLoader.get_int('RETRY_COUNT', 3)
# Feature flags
FEATURES = EnvLoader.get_list('FEATURES', default=['feature1', 'feature2'])
# File paths
LOG_DIR = EnvLoader.get_path('LOG_DIR', Path('./logs'))
# Usage example
try:
config = Config()
print(f"Database: {config.DB_HOST}:{config.DB_PORT}/{config.DB_NAME}")
print(f"Debug mode: {config.DEBUG}")
print(f"Features: {config.FEATURES}")
print(f"Log directory: {config.LOG_DIR}")
except ValueError as e:
print(f"Configuration error: {e}")
This environment variable loader provides a robust way to manage application configuration using environment variables. It offers:
Environment variables are the standard way to configure applications, especially in containerized environments like Docker or cloud platforms. This utility solves common problems:
env_loader.pyexport DB_NAME=myapp
export API_KEY=secret123
export DEBUG=true
export RETRY_COUNT=5
export FEATURES=auth,cache,metrics
python env_loader.py
The code will load the environment variables, convert them to appropriate types, validate them, and print the configuration. If required variables are missing or have invalid values, it will show descriptive error messages.