Ejemplos de Manejo de Errores Web Python

Ejemplos de manejo de errores Web Python incluyendo captura de excepciones, registro y validación de parámetros

💻 Captura de Excepciones python

🟢 simple ⭐⭐

Manejar excepciones usando bloques try-except con múltiples tipos de excepción, bloques else/finally y encadenamiento de excepciones

⏱️ 25 min 🏷️ python, web, error handling, exception
Prerequisites: Basic Python, exception handling
# Web Python Exception Catching Examples
# Comprehensive exception handling patterns

# 1. Basic Try-Except
from typing import Optional, Any
import sys

def divide_basic(a: float, b: float) -> Optional[float]:
    """
    Basic division with exception handling

    Args:
        a: Numerator
        b: Denominator

    Returns:
        Result or None if error
    """
    try:
        return a / b
    except ZeroDivisionError:
        print("Error: Division by zero")
        return None

def safe_divide(a: float, b: float) -> float:
    """
    Safe division with custom error message

    Args:
        a: Numerator
        b: Denominator

    Returns:
        Division result

    Raises:
        ValueError: If denominator is zero
    """
    if b == 0:
        raise ValueError("Denominator cannot be zero")
    return a / b

# 2. Multiple Except Blocks
def handle_multiple_exceptions(value: Any) -> str:
    """
    Handle multiple exception types

    Args:
        value: Input value of any type

    Returns:
        Result string or error message
    """
    try:
        result = int(value)
        return f"Converted to integer: {result}"
    except ValueError:
        return f"Error: '{value}' cannot be converted to integer"
    except TypeError:
        return f"Error: Invalid type {type(value)}"
    except Exception as e:
        return f"Unexpected error: {e}"

def parse_input(input_str: str) -> dict:
    """
    Parse input with multiple exception handlers

    Args:
        input_str: Input string

    Returns:
        Dictionary with parsed data
    """
    try:
        # Try to evaluate as expression
        result = eval(input_str)
        return {'type': 'expression', 'value': result}
    except SyntaxError:
        try:
            # Try to parse as JSON
            import json
            result = json.loads(input_str)
            return {'type': 'json', 'value': result}
        except json.JSONDecodeError:
            return {'type': 'string', 'value': input_str}
    except Exception as e:
        return {'type': 'error', 'value': str(e)}

# 3. Else and Finally Blocks
def process_file(filepath: str) -> Optional[str]:
    """
    Process file with finally block for cleanup

    Args:
        filepath: Path to file

    Returns:
        File content or None
    """
    file = None
    try:
        file = open(filepath, 'r')
        content = file.read()
        print(f"Successfully read {len(content)} characters")
        return content
    except FileNotFoundError:
        print(f"Error: File '{filepath}' not found")
        return None
    except IOError as e:
        print(f"Error reading file: {e}")
        return None
    else:
        print("File processing completed successfully")
        return content
    finally:
        if file:
            file.close()
            print("File closed")

def divide_with_logging(a: float, b: float) -> Optional[float]:
    """
    Division with logging in else block

    Args:
        a: Numerator
        b: Denominator

    Returns:
        Result or None
    """
    try:
        result = a / b
    except ZeroDivisionError:
        print("Division by zero occurred")
        return None
    else:
        print(f"Division successful: {a} / {b} = {result}")
        return result
    finally:
        print("Division attempt completed")

# 4. Specific Exception Handling
def handle_specific_errors(data: dict, key: str) -> Any:
    """
    Handle specific dictionary errors

    Args:
        data: Dictionary
        key: Key to access

    Returns:
        Value or default
    """
    try:
        return data[key]
    except KeyError:
        print(f"Key '{key}' not found")
        return None
    except TypeError:
        print("Error: data is not a dictionary")
        return None

def safe_list_access(lst: list, index: int) -> Optional[Any]:
    """
    Safe list access with error handling

    Args:
        lst: List
        index: Index to access

    Returns:
        Element or None
    """
    try:
        return lst[index]
    except IndexError:
        print(f"Index {index} out of range")
        return None
    except TypeError:
        print("Error: Invalid index type")
        return None

# 5. Exception Chaining
def chain_exceptions(value: str) -> int:
    """
    Demonstrate exception chaining

    Args:
        value: String to parse

    Returns:
        Parsed integer

    Raises:
        ValueError: With chained original exception
    """
    try:
        number = int(value)
        if number < 0:
            raise ValueError("Number must be positive")
        return number
    except ValueError as e:
        # Chain with original exception
        raise ValueError(f"Invalid input '{value}': {e}") from e

def nested_exception_handling(filepath: str) -> str:
    """
    Nested exception handling with chaining

    Args:
        filepath: File path

    Returns:
        File content

    Raises:
        IOError: With chained exception
    """
    try:
        try:
            with open(filepath, 'r') as f:
                return f.read()
        except FileNotFoundError as e:
            raise IOError(f"File not found: {filepath}") from e
    except IOError as e:
        raise IOError(f"Failed to read file: {filepath}") from e

# 6. Context Manager Exception Handling
def read_with_context_manager(filepath: str) -> Optional[str]:
    """
    Read file using context manager with exception handling

    Args:
        filepath: File path

    Returns:
        File content or None
    """
    try:
        with open(filepath, 'r') as f:
            return f.read()
    except FileNotFoundError:
        print(f"File '{filepath}' not found")
        return None
    except IOError as e:
        print(f"Error reading file: {e}")
        return None

class CustomFileManager:
    """Custom context manager for file operations"""

    def __init__(self, filepath: str, mode: str = 'r'):
        self.filepath = filepath
        self.mode = mode
        self.file = None

    def __enter__(self):
        try:
            self.file = open(self.filepath, self.mode)
            return self.file
        except IOError as e:
            print(f"Error opening file: {e}")
            raise

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.file:
            self.file.close()
        if exc_type is not None:
            print(f"Exception occurred: {exc_type.__name__}: {exc_val}")
            return False  # Re-raise exception
        return True

# 7. Custom Exceptions
class CustomError(Exception):
    """Base custom exception"""
    pass

class ValidationError(CustomError):
    """Validation error"""
    def __init__(self, message: str, field: str = None):
        self.field = field
        super().__init__(message)

class NotFoundError(CustomError):
    """Resource not found error"""
    pass

def validate_age(age: int) -> None:
    """
    Validate age with custom exception

    Args:
        age: Age to validate

    Raises:
        ValidationError: If age is invalid
    """
    if age < 0:
        raise ValidationError("Age cannot be negative", "age")
    if age > 150:
        raise ValidationError("Age seems unrealistic", "age")

def find_user(user_id: int) -> dict:
    """
    Find user with custom exception

    Args:
        user_id: User ID

    Returns:
        User data

    Raises:
        NotFoundError: If user not found
    """
    # Simulate user lookup
    users = {1: {'name': 'Alice'}, 2: {'name': 'Bob'}}

    if user_id not in users:
        raise NotFoundError(f"User {user_id} not found")

    return users[user_id]

# 8. Exception Suppression
def suppress_exception(func, *args, **kwargs) -> Optional[Any]:
    """
    Suppress exceptions from function call

    Args:
        func: Function to call
        *args: Positional arguments
        **kwargs: Keyword arguments

    Returns:
        Result or None
    """
    try:
        return func(*args, **kwargs)
    except Exception:
        return None

def safe_execute(func, *args, default=None, **kwargs) -> Any:
    """
    Execute function with default on exception

    Args:
        func: Function to call
        *args: Positional arguments
        default: Default value on exception
        **kwargs: Keyword arguments

    Returns:
        Result or default value
    """
    try:
        return func(*args, **kwargs)
    except Exception:
        return default

# 9. Exception Information
def get_exception_info() -> dict:
    """
    Get detailed exception information

    Returns:
        Dictionary with exception info
    """
    try:
        result = 1 / 0
    except Exception as e:
        return {
            'type': type(e).__name__,
            'message': str(e),
            'args': e.args,
            'traceback': sys.exc_info()[2]
        }

def log_exception(exc: Exception, context: str = "") -> None:
    """
    Log exception with context

    Args:
        exc: Exception object
        context: Additional context
    """
    import traceback

    print(f"Exception in {context}:")
    print(f"  Type: {type(exc).__name__}")
    print(f"  Message: {exc}")
    print(f"  Traceback:")
    traceback.print_exc()

# 10. Retry Pattern
def retry_on_exception(func, max_attempts: int = 3, exceptions: tuple = (Exception,)):
    """
    Retry function on exception

    Args:
        func: Function to retry
        max_attempts: Maximum number of attempts
        exceptions: Exception types to catch

    Returns:
        Function result

    Raises:
        Exception: If all attempts fail
    """
    import time

    for attempt in range(max_attempts):
        try:
            return func()
        except exceptions as e:
            if attempt == max_attempts - 1:
                raise
            print(f"Attempt {attempt + 1} failed, retrying...")
            time.sleep(1)

# Usage Examples
def demonstrate_exception_catching():
    print("=== Web Python Exception Catching Examples ===\n")

    # 1. Basic try-except
    print("--- 1. Basic Try-Except ---")
    print(divide_basic(10, 2))
    print(divide_basic(10, 0))

    # 2. Multiple exceptions
    print("\n--- 2. Multiple Exception Types ---")
    print(handle_multiple_exceptions("42"))
    print(handle_multiple_exceptions("abc"))
    print(handle_multiple_exceptions(None))

    # 3. Else and finally
    print("\n--- 3. Else and Finally Blocks ---")
    print("Note: File operations in examples")
    print("# Example structure:")
    print("try:")
    print("    result = risky_operation()")
    print("except SpecificError:")
    print("    handle_error()")
    print("else:")
    print("    print('Success!')")
    print("finally:")
    print("    cleanup()")

    # 4. Specific exceptions
    print("\n--- 4. Specific Exception Handling ---")
    data = {'name': 'Alice', 'age': 30}
    print(handle_specific_errors(data, 'name'))
    print(handle_specific_errors(data, 'email'))
    print(safe_list_access([1, 2, 3], 1))
    print(safe_list_access([1, 2, 3], 10))

    # 5. Exception chaining
    print("\n--- 5. Exception Chaining ---")
    try:
        chain_exceptions("-5")
    except ValueError as e:
        print(f"Chained error: {e}")
        print(f"Original cause: {e.__cause__}")

    # 6. Custom exceptions
    print("\n--- 6. Custom Exceptions ---")
    try:
        validate_age(-5)
    except ValidationError as e:
        print(f"Validation error: {e} (field: {e.field})")

    try:
        find_user(999)
    except NotFoundError as e:
        print(f"Not found: {e}")

    # 7. Exception suppression
    print("\n--- 7. Exception Suppression ---")
    print(f"Suppress: {suppress_exception(lambda: 1/0)}")
    print(f"Safe execute: {safe_execute(lambda: 1/0, default='Error handled')}")

    # 8. Exception info
    print("\n--- 8. Exception Information ---")
    info = get_exception_info()
    print(f"Exception type: {info['type']}")
    print(f"Message: {info['message']}")

    # 9. Retry pattern
    print("\n--- 9. Retry Pattern ---")
    attempts = 0
    def failing_func():
        nonlocal attempts
        attempts += 1
        if attempts < 3:
            raise ValueError("Not yet!")
        return "Success!"

    result = retry_on_exception(failing_func)
    print(f"Retry result: {result}")

    print("\n=== All Exception Catching Examples Completed ===")

# Export functions
export { divide_basic, safe_divide }
export { handle_multiple_exceptions, parse_input }
export { process_file, divide_with_logging }
export { handle_specific_errors, safe_list_access }
export { chain_exceptions, nested_exception_handling }
export { read_with_context_manager, CustomFileManager }
export { ValidationError, NotFoundError, validate_age, find_user }
export { suppress_exception, safe_execute }
export { get_exception_info, log_exception }
export { retry_on_exception }
export { demonstrate_exception_catching }

💻 Registro de Log python

🟡 intermediate ⭐⭐⭐

Implementar registro completo con diferentes niveles, formatos, controladores de archivo y rotación de logs

⏱️ 30 min 🏷️ python, web, error handling, logging
Prerequisites: Intermediate Python, logging module
# Web Python Logging Examples
# Comprehensive logging system implementation

# 1. Basic Logging
import logging
from typing import Optional
import sys
from datetime import datetime
import os

def setup_basic_logging():
    """Configure basic logging to console"""
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(levelname)s - %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S'
    )

def basic_logging_examples():
    """Demonstrate basic logging levels"""
    logging.debug("This is a debug message")
    logging.info("This is an info message")
    logging.warning("This is a warning message")
    logging.error("This is an error message")
    logging.critical("This is a critical message")

# 2. Custom Logger
def create_logger(name: str, level: int = logging.INFO) -> logging.Logger:
    """
    Create custom logger

    Args:
        name: Logger name
        level: Logging level

    Returns:
        Logger instance
    """
    logger = logging.getLogger(name)
    logger.setLevel(level)

    # Avoid duplicate handlers
    if not logger.handlers:
        # Console handler
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setLevel(level)

        # Formatter
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S'
        )
        console_handler.setFormatter(formatter)

        logger.addHandler(console_handler)

    return logger

# 3. File Logging
def setup_file_logging(filepath: str, level: int = logging.INFO) -> logging.Logger:
    """
    Setup file logging

    Args:
        filepath: Log file path
        level: Logging level

    Returns:
        Logger instance
    """
    # Create directory if needed
    os.makedirs(os.path.dirname(filepath) or '.', exist_ok=True)

    logger = logging.getLogger('file_logger')
    logger.setLevel(level)

    # Remove existing handlers
    logger.handlers.clear()

    # File handler
    file_handler = logging.FileHandler(filepath)
    file_handler.setLevel(level)

    # Formatter
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s'
    )
    file_handler.setFormatter(formatter)

    logger.addHandler(file_handler)

    return logger

def setup_dual_logging(log_file: str, console_level: int = logging.INFO, file_level: int = logging.DEBUG) -> logging.Logger:
    """
    Setup both console and file logging

    Args:
        log_file: Log file path
        console_level: Console logging level
        file_level: File logging level

    Returns:
        Logger instance
    """
    logger = logging.getLogger('dual_logger')
    logger.setLevel(logging.DEBUG)

    logger.handlers.clear()

    # Console handler
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setLevel(console_level)
    console_formatter = logging.Formatter('%(levelname)s: %(message)s')
    console_handler.setFormatter(console_formatter)
    logger.addHandler(console_handler)

    # File handler
    file_handler = logging.FileHandler(log_file)
    file_handler.setLevel(file_level)
    file_formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s'
    )
    file_handler.setFormatter(file_formatter)
    logger.addHandler(file_handler)

    return logger

# 4. Log Levels
def log_all_levels(logger: logging.Logger):
    """
    Log messages at all levels

    Args:
        logger: Logger instance
    """
    logger.debug("Debug message - detailed information for diagnosing problems")
    logger.info("Info message - confirmation that things are working as expected")
    logger.warning("Warning message - something unexpected happened")
    logger.error("Error message - serious problem occurred")
    logger.critical("Critical message - serious error, program may be unable to continue")

# 5. Formatted Logging
def setup_formatted_logging(format_string: str) -> logging.Logger:
    """
    Setup logging with custom format

    Args:
        format_string: Custom format string

    Returns:
        Logger instance
    """
    logger = logging.getLogger('formatted_logger')
    logger.setLevel(logging.INFO)

    logger.handlers.clear()

    handler = logging.StreamHandler(sys.stdout)
    formatter = logging.Formatter(format_string)
    handler.setFormatter(formatter)
    logger.addHandler(handler)

    return logger

def get_format_examples() -> dict:
    """Get example format strings"""
    return {
        'simple': '%(levelname)s: %(message)s',
        'detailed': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        'verbose': '%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s',
        'json': '{"time": "%(asctime)s", "level": "%(levelname)s", "message": "%(message)s"}'
    }

# 6. Log Rotation
def setup_rotating_file_log(log_file: str, max_bytes: int = 1048576, backup_count: int = 5) -> logging.Logger:
    """
    Setup rotating file logging

    Args:
        log_file: Log file path
        max_bytes: Max file size before rotation
        backup_count: Number of backup files to keep

    Returns:
        Logger instance
    """
    from logging.handlers import RotatingFileHandler

    logger = logging.getLogger('rotating_logger')
    logger.setLevel(logging.INFO)

    logger.handlers.clear()

    handler = RotatingFileHandler(
        log_file,
        maxBytes=max_bytes,
        backupCount=backup_count
    )
    handler.setLevel(logging.INFO)

    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    handler.setFormatter(formatter)

    logger.addHandler(handler)

    return logger

def setup_time_based_rotation(log_file: str, when: str = 'midnight', interval: int = 1, backup_count: int = 7) -> logging.Logger:
    """
    Setup time-based log rotation

    Args:
        log_file: Log file path
        when: When to rotate ('S', 'M', 'H', 'D', 'midnight', 'W0-W6')
        interval: Rotation interval
        backup_count: Number of backups to keep

    Returns:
        Logger instance
    """
    from logging.handlers import TimedRotatingFileHandler

    logger = logging.getLogger('time_rotating_logger')
    logger.setLevel(logging.INFO)

    logger.handlers.clear()

    handler = TimedRotatingFileHandler(
        log_file,
        when=when,
        interval=interval,
        backupCount=backup_count
    )
    handler.setLevel(logging.INFO)

    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    handler.setFormatter(formatter)

    logger.addHandler(handler)

    return logger

# 7. Structured Logging
class StructuredLogger:
    """Structured logger with contextual information"""

    def __init__(self, name: str):
        self.logger = logging.getLogger(name)
        self.logger.setLevel(logging.INFO)
        if not self.logger.handlers:
            handler = logging.StreamHandler(sys.stdout)
            handler.setFormatter(logging.Formatter('%(message)s'))
            self.logger.addHandler(handler)

    def log(self, level: int, message: str, **context):
        """
        Log structured message

        Args:
            level: Log level
            message: Log message
            **context: Additional context
        """
        import json
        log_data = {
            'message': message,
            'timestamp': datetime.now().isoformat(),
            **context
        }
        self.logger.log(level, json.dumps(log_data))

    def debug(self, message: str, **context):
        """Log debug message"""
        self.log(logging.DEBUG, message, **context)

    def info(self, message: str, **context):
        """Log info message"""
        self.log(logging.INFO, message, **context)

    def warning(self, message: str, **context):
        """Log warning message"""
        self.log(logging.WARNING, message, **context)

    def error(self, message: str, **context):
        """Log error message"""
        self.log(logging.ERROR, message, **context)

# 8. Contextual Logging
class ContextualLogger:
    """Logger with automatic context"""

    def __init__(self, name: str, context: dict = None):
        self.logger = logging.getLogger(name)
        self.context = context or {}

    def with_context(self, **context) -> 'ContextualLogger':
        """Create new logger with additional context"""
        new_context = {**self.context, **context}
        return ContextualLogger(self.logger.name, new_context)

    def _log(self, level: int, message: str, **extra_context):
        """Log with context"""
        all_context = {**self.context, **extra_context}
        log_message = f"{message} | Context: {all_context}"
        self.logger.log(level, log_message)

    def info(self, message: str, **context):
        """Info level log"""
        self._log(logging.INFO, message, **context)

    def error(self, message: str, **context):
        """Error level log"""
        self._log(logging.ERROR, message, **context)

# 9. Exception Logging
def log_exception(logger: logging.Logger, exc: Exception, context: str = ""):
    """
    Log exception with traceback

    Args:
        logger: Logger instance
        exc: Exception object
        context: Additional context
    """
    logger.error(f"Exception in {context}: {exc}", exc_info=True)

def safe_execute_with_logging(logger: logging.Logger, func, *args, **kwargs):
    """
    Execute function with exception logging

    Args:
        logger: Logger instance
        func: Function to execute
        *args: Positional arguments
        **kwargs: Keyword arguments

    Returns:
        Function result or None
    """
    try:
        return func(*args, **kwargs)
    except Exception as e:
        log_exception(logger, e, f"function '{func.__name__}'")
        return None

# 10. Performance Logging
class PerformanceLogger:
    """Logger for performance monitoring"""

    def __init__(self, logger: logging.Logger):
        self.logger = logger
        self.start_times = {}

    def start(self, operation: str):
        """Start timing operation"""
        self.start_times[operation] = datetime.now()

    def end(self, operation: str):
        """End timing and log duration"""
        if operation in self.start_times:
            duration = (datetime.now() - self.start_times[operation]).total_seconds()
            self.logger.info(f"Operation '{operation}' completed in {duration:.3f}s")
            del self.start_times[operation]

# Usage Examples
def demonstrate_logging():
    print("=== Web Python Logging Examples ===\n")

    print("--- 1. Basic Logging ---")
    setup_basic_logging()
    basic_logging_examples()

    print("\n--- 2. Custom Logger ---")
    logger = create_logger('my_app', level=logging.DEBUG)
    logger.debug("Debug message")
    logger.info("Info message")
    logger.warning("Warning message")

    print("\n--- 3. File Logging ---")
    file_logger = setup_file_logging('app.log')
    file_logger.info("This goes to file")
    file_logger.error("Error in file")
    print("Check 'app.log' for file output")

    print("\n--- 4. Dual Logging ---")
    dual_logger = setup_dual_logging('dual.log')
    dual_logger.debug("Debug to file only")
    dual_logger.info("Info to both console and file")

    print("\n--- 5. Structured Logging ---")
    struct_logger = StructuredLogger('structured')
    struct_logger.info("User login", user_id=123, ip="192.168.1.1")
    struct_logger.error("Database error", error_code=500, query="SELECT * FROM users")

    print("\n--- 6. Contextual Logging ---")
    base_logger = ContextualLogger('app', context={'app': 'my_app', 'version': '1.0'})
    base_logger.info("Application started")
    request_logger = base_logger.with_context(request_id='abc123', user='alice')
    request_logger.info("Processing request")

    print("\n--- 7. Rotating File Handler ---")
    rotating_logger = setup_rotating_file_log('rotating.log', max_bytes=1024, backup_count=3)
    for i in range(100):
        rotating_logger.info(f"Log message {i}")
    print("Check 'rotating.log' for rotating output")

    print("\n--- 8. Exception Logging ---")
    try:
        1 / 0
    except Exception as e:
        log_exception(logger, e, "demonstration")

    print("\n--- 9. Performance Logging ---")
    perf_logger = PerformanceLogger(logger)
    perf_logger.start('data_processing')
    import time
    time.sleep(0.1)
    perf_logger.end('data_processing')

    print("\n=== All Logging Examples Completed ===")

# Export functions
export { setup_basic_logging, basic_logging_examples }
export { create_logger }
export { setup_file_logging, setup_dual_logging }
export { log_all_levels }
export { setup_formatted_logging, get_format_examples }
export { setup_rotating_file_log, setup_time_based_rotation }
export { StructuredLogger }
export { ContextualLogger }
export { log_exception, safe_execute_with_logging }
export { PerformanceLogger }
export { demonstrate_logging }

💻 Validación de Parámetros python

🟡 intermediate ⭐⭐⭐

Validar parámetros de función usando verificación de tipos, validación de rango, validadores personalizados y dataclasses

⏱️ 35 min 🏷️ python, web, error handling, validation
Prerequisites: Intermediate Python, decorators, dataclasses
# Web Python Parameter Validation Examples
# Comprehensive parameter validation techniques

# 1. Type Checking
from typing import Any, Optional, List, Type, get_type_hints
import re
from datetime import datetime
from dataclasses import dataclass
from enum import Enum

def validate_type(value: Any, expected_type: Type, param_name: str = "parameter") -> None:
    """
    Validate value type

    Args:
        value: Value to check
        expected_type: Expected type
        param_name: Parameter name for error message

    Raises:
        TypeError: If type mismatch
    """
    if not isinstance(value, expected_type):
        raise TypeError(f"{param_name} must be {expected_type.__name__}, got {type(value).__name__}")

def validate_types(**params) -> None:
    """
    Validate multiple parameters

    Args:
        **params: Parameter name and (value, type) tuples

    Raises:
        TypeError: If any type mismatch
    """
    for param_name, (value, expected_type) in params.items():
        validate_type(value, expected_type, param_name)

def typed_function(name: str, age: int, scores: List[float]) -> str:
    """
    Function with type validation

    Args:
        name: Person name (string)
        age: Person age (integer)
        scores: List of scores

    Returns:
        Formatted string

    Raises:
        TypeError: If any parameter has wrong type
    """
    validate_types(
        name=(name, str),
        age=(age, int),
        scores=(scores, list)
    )

    # Validate list elements
    for i, score in enumerate(scores):
        validate_type(score, float, f"scores[{i}]")

    return f"{name}, age {age}, scores: {scores}"

# 2. Range Validation
def validate_range(value: int, min_val: Optional[int] = None, max_val: Optional[int] = None, param_name: str = "parameter") -> None:
    """
    Validate numeric range

    Args:
        value: Value to check
        min_val: Minimum value (None = no minimum)
        max_val: Maximum value (None = no maximum)
        param_name: Parameter name

    Raises:
        ValueError: If out of range
    """
    if min_val is not None and value < min_val:
        raise ValueError(f"{param_name} must be >= {min_val}, got {value}")

    if max_val is not None and value > max_val:
        raise ValueError(f"{param_name} must be <= {max_val}, got {value}")

def validate_positive(value: int, param_name: str = "parameter") -> None:
    """Validate positive value"""
    validate_range(value, min_val=1, param_name=param_name)

def validate_non_negative(value: int, param_name: str = "parameter") -> None:
    """Validate non-negative value"""
    validate_range(value, min_val=0, param_name=param_name)

def validate_percentage(value: float, param_name: str = "parameter") -> None:
    """Validate percentage (0-100)"""
    validate_range(value, min_val=0, max_val=100, param_name=param_name)

def validate_length(value: List, min_length: Optional[int] = None, max_length: Optional[int] = None, param_name: str = "parameter") -> None:
    """
    Validate list length

    Args:
        value: List to check
        min_length: Minimum length
        max_length: Maximum length
        param_name: Parameter name
    """
    length = len(value)
    validate_range(length, min_length, max_length, f"{param_name} length")

# 3. String Validation
def validate_string_length(value: str, min_length: int = 0, max_length: Optional[int] = None, param_name: str = "parameter") -> None:
    """
    Validate string length

    Args:
        value: String to validate
        min_length: Minimum length
        max_length: Maximum length
        param_name: Parameter name
    """
    validate_type(value, str, param_name)
    validate_range(len(value), min_length, max_length, param_name)

def validate_email(value: str, param_name: str = "email") -> None:
    """
    Validate email format

    Args:
        value: Email string
        param_name: Parameter name

    Raises:
        ValueError: If invalid email format
    """
    validate_type(value, str, param_name)

    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    if not re.match(pattern, value):
        raise ValueError(f"{param_name} must be a valid email address")

def validate_url(value: str, param_name: str = "url") -> None:
    """
    Validate URL format

    Args:
        value: URL string
        param_name: Parameter name

    Raises:
        ValueError: If invalid URL format
    """
    validate_type(value, str, param_name)

    pattern = r'^https?://[a-zA-Z0-9.-]+(\.[a-zA-Z]{2,})?(/.*)?$'
    if not re.match(pattern, value):
        raise ValueError(f"{param_name} must be a valid URL")

def validate_regex(value: str, pattern: str, param_name: str = "parameter") -> None:
    """
    Validate string against regex pattern

    Args:
        value: String to validate
        pattern: Regex pattern
        param_name: Parameter name
    """
    validate_type(value, str, param_name)

    if not re.match(pattern, value):
        raise ValueError(f"{param_name} does not match required pattern")

def validate_phone(value: str, param_name: str = "phone") -> None:
    """
    Validate phone number format

    Args:
        value: Phone number string
        param_name: Parameter name
    """
    validate_type(value, str, param_name)

    # Allow formats: (123) 456-7890, 123-456-7890, 123.456.7890, 1234567890
    pattern = r'^\(?(\d{3})\)?[-.\s]?(\d{3})[-.\s]?(\d{4})$'
    if not re.match(pattern, value):
        raise ValueError(f"{param_name} must be a valid phone number")

# 4. Date Validation
def validate_date(value: str, format: str = "%Y-%m-%d", param_name: str = "date") -> datetime:
    """
    Validate and parse date string

    Args:
        value: Date string
        format: Expected date format
        param_name: Parameter name

    Returns:
        Parsed datetime object

    Raises:
        ValueError: If invalid date
    """
    validate_type(value, str, param_name)

    try:
        return datetime.strptime(value, format)
    except ValueError:
        raise ValueError(f"{param_name} must be a valid date in format {format}")

def validate_date_range(start_date: str, end_date: str, format: str = "%Y-%m-%d") -> None:
    """
    Validate date range (start <= end)

    Args:
        start_date: Start date string
        end_date: End date string
        format: Date format
    """
    start = validate_date(start_date, format, "start_date")
    end = validate_date(end_date, format, "end_date")

    if start > end:
        raise ValueError("start_date must be before or equal to end_date")

def validate_age(value: int, param_name: str = "age") -> None:
    """Validate age (0-150)"""
    validate_range(value, 0, 150, param_name)

# 5. Custom Validators
class ValidationError(Exception):
    """Custom validation error"""
    def __init__(self, message: str, field: str = None):
        self.field = field
        super().__init__(message)

def validate_username(value: str) -> None:
    """
    Validate username format

    Args:
        value: Username string

    Raises:
        ValidationError: If invalid username
    """
    validate_string_length(value, min_length=3, max_length=20, param_name="username")

    # Alphanumeric and underscores only
    if not re.match(r'^[a-zA-Z0-9_]+$', value):
        raise ValidationError("Username can only contain letters, numbers, and underscores", "username")

def validate_password(value: str, min_length: int = 8) -> None:
    """
    Validate password strength

    Args:
        value: Password string
        min_length: Minimum length

    Raises:
        ValidationError: If password too weak
    """
    validate_string_length(value, min_length=min_length, param_name="password")

    # Must contain uppercase, lowercase, and digit
    if not re.search(r'[A-Z]', value):
        raise ValidationError("Password must contain at least one uppercase letter", "password")

    if not re.search(r'[a-z]', value):
        raise ValidationError("Password must contain at least one lowercase letter", "password")

    if not re.search(r'\d', value):
        raise ValidationError("Password must contain at least one digit", "password")

# 6. Dataclass Validation
@dataclass
class User:
    """User with validation"""
    name: str
    email: str
    age: int

    def __post_init__(self):
        """Validate after initialization"""
        validate_string_length(self.name, min_length=1, max_length=100, param_name="name")
        validate_email(self.email, param_name="email")
        validate_age(self.age, param_name="age")

@dataclass
class Product:
    """Product with validation"""
    name: str
    price: float
    stock: int

    def __post_init__(self):
        """Validate product data"""
        validate_string_length(self.name, min_length=1, param_name="name")
        validate_range(self.price, min_val=0, param_name="price")
        validate_non_negative(self.stock, param_name="stock")

# 7. Enum Validation
class Status(Enum):
    """Status enum"""
    PENDING = "pending"
    ACTIVE = "active"
    INACTIVE = "inactive"
    CANCELLED = "cancelled"

def validate_enum(value: str, enum_class: Type[Enum], param_name: str = "parameter") -> Enum:
    """
    Validate enum value

    Args:
        value: String value
        enum_class: Enum class
        param_name: Parameter name

    Returns:
        Enum value

    Raises:
        ValueError: If invalid enum value
    """
    valid_values = [e.value for e in enum_class]

    if value not in valid_values:
        raise ValueError(f"{param_name} must be one of {valid_values}, got '{value}'")

    return enum_class(value)

# 8. Required Parameters
def validate_required(value: Any, param_name: str = "parameter") -> None:
    """
    Validate required parameter

    Args:
        value: Value to check
        param_name: Parameter name

    Raises:
        ValueError: If value is None or empty
    """
    if value is None:
        raise ValueError(f"{param_name} is required")

    if isinstance(value, str) and len(value.strip()) == 0:
        raise ValueError(f"{param_name} cannot be empty")

    if isinstance(value, (list, dict)) and len(value) == 0:
        raise ValueError(f"{param_name} cannot be empty")

# 9. Composite Validation
def validate_user_data(name: str, email: str, age: int, **kwargs) -> None:
    """
    Validate complete user data

    Args:
        name: User name
        email: User email
        age: User age
        **kwargs: Additional fields

    Raises:
        ValidationError: If any validation fails
    """
    # Required fields
    validate_required(name, "name")
    validate_required(email, "email")
    validate_required(age, "age")

    # Type validation
    validate_types(
        name=(name, str),
        email=(email, str),
        age=(age, int)
    )

    # Format validation
    validate_string_length(name, min_length=2, max_length=50, param_name="name")
    validate_email(email)
    validate_age(age)

    # Optional fields
    if 'phone' in kwargs:
        validate_phone(kwargs['phone'])

    if 'address' in kwargs:
        validate_string_length(kwargs['address'], min_length=5, param_name="address")

# 10. Validation Decorator
def validate_params(**validators):
    """
    Decorator for parameter validation

    Args:
        **validators: Parameter name -> validator function mappings

    Returns:
        Decorated function
    """
    def decorator(func):
        def wrapper(*args, **kwargs):
            # Get function signature
            import inspect
            sig = inspect.signature(func)
            bound_args = sig.bind(*args, **kwargs)
            bound_args.apply_defaults()

            # Validate each parameter
            for param_name, value in bound_args.arguments.items():
                if param_name in validators:
                    validators[param_name](value)

            return func(*args, **kwargs)
        return wrapper
    return decorator

# Usage Examples
def demonstrate_parameter_validation():
    print("=== Web Python Parameter Validation Examples ===\n")

    # 1. Type checking
    print("--- 1. Type Checking ---")
    try:
        print(typed_function("Alice", 30, [85.5, 90.0, 88.5]))
    except TypeError as e:
        print(f"Type error: {e}")

    # 2. Range validation
    print("\n--- 2. Range Validation ---")
    try:
        validate_range(50, min_val=0, max_val=100)
        print("Valid: 50 in range [0, 100]")

        validate_range(150, min_val=0, max_val=100)
    except ValueError as e:
        print(f"Range error: {e}")

    # 3. String validation
    print("\n--- 3. String Validation ---")
    try:
        validate_email("[email protected]")
        print("Valid email")

        validate_email("invalid-email")
    except ValueError as e:
        print(f"Email error: {e}")

    # 4. Date validation
    print("\n--- 4. Date Validation ---")
    try:
        date = validate_date("2025-12-31")
        print(f"Valid date: {date}")

        validate_date("31/12/2025")
    except ValueError as e:
        print(f"Date error: {e}")

    # 5. Custom validators
    print("\n--- 5. Custom Validators ---")
    try:
        validate_username("user123")
        print("Valid username")

        validate_username("us")
    except ValidationError as e:
        print(f"Username error: {e}")

    try:
        validate_password("StrongPass123")
        print("Valid password")

        validate_password("weak")
    except ValidationError as e:
        print(f"Password error: {e}")

    # 6. Dataclass validation
    print("\n--- 6. Dataclass Validation ---")
    try:
        user = User(name="Alice", email="[email protected]", age=30)
        print(f"Valid user: {user}")

        invalid_user = User(name="", email="invalid", age=-5)
    except (ValueError, TypeError) as e:
        print(f"Dataclass error: {e}")

    # 7. Enum validation
    print("\n--- 7. Enum Validation ---")
    try:
        status = validate_enum("active", Status)
        print(f"Valid status: {status.value}")

        validate_enum("invalid", Status)
    except ValueError as e:
        print(f"Enum error: {e}")

    # 8. Validation decorator
    print("\n--- 8. Validation Decorator ---")

    @validate_params(
        name=lambda x: validate_string_length(x, min_length=2, param_name="name"),
        age=lambda x: validate_range(x, 0, 150, param_name="age")
    )
    def create_user(name: str, age: int):
        return f"User: {name}, Age: {age}"

    try:
        print(create_user("Alice", 30))
        print(create_user("A", 30))
    except ValueError as e:
        print(f"Decorator error: {e}")

    print("\n=== All Parameter Validation Examples Completed ===")

# Export functions
export { validate_type, validate_types, typed_function }
export { validate_range, validate_positive, validate_non_negative, validate_percentage, validate_length }
export { validate_string_length, validate_email, validate_url, validate_regex, validate_phone }
export { validate_date, validate_date_range, validate_age }
export { ValidationError, validate_username, validate_password }
export { User, Product }
export { validate_enum, Status }
export { validate_required }
export { validate_user_data }
export { validate_params }
export { demonstrate_parameter_validation }