🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

पायथन त्रुटि प्रबंधन सर्वोत्तम अभ्यास 2026: अपवाद, लॉगिंग और पुनः प्रयास

⏱️4 min read  ·  809 words

पायथन त्रुटि प्रबंधन उत्पादन कोडबेस में सबसे कम निवेश वाले क्षेत्रों में से एक है। 2026 में, बेहतर अपवाद समूहों (पायथन 3.11+), संरचित लॉगिंग और स्वच्छ त्रुटि प्रसार पैटर्न के साथ, विश्वसनीय पायथन कोड लिखना जो शानदार ढंग से विफल हो जाता है, पहले से कहीं अधिक आसान है। यह मार्गदर्शिका प्रत्येक पैटर्न को कवर करती है।

अपवाद पदानुक्रम और कस्टम अपवाद

# Well-designed exception hierarchy for a FastAPI app
class AppError(Exception):
    def __init__(self, message: str, code: str = "UNKNOWN_ERROR"):
        super().__init__(message)
        self.message = message
        self.code = code

class ValidationError(AppError):
    def __init__(self, field: str, message: str):
        super().__init__(f"Validation error on '{field}': {message}", "VALIDATION_ERROR")
        self.field = field

class NotFoundError(AppError):
    def __init__(self, resource: str, id: str | int):
        super().__init__(f"{resource} not found: {id}", "NOT_FOUND")
        self.resource = resource
        self.resource_id = id

class AuthorizationError(AppError):
    def __init__(self, action: str = "perform this action"):
        super().__init__(f"Not authorized to {action}", "UNAUTHORIZED")

class DatabaseError(AppError):
    def __init__(self, operation: str, original: Exception):
        super().__init__(f"Database error during {operation}: {original}", "DATABASE_ERROR")
        self.original = original
        self.__cause__ = original  # sets __cause__ for proper chaining

# Usage
raise NotFoundError("User", user_id)
raise ValidationError("email", "must be a valid email address")

# Exception chaining (raise from)
try:
    await db.users.get(user_id)
except asyncpg.PostgresError as e:
    raise DatabaseError("user lookup", e) from e

फास्टएपीआई त्रुटि हैंडलर

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()

@app.exception_handler(AppError)
async def app_error_handler(request: Request, exc: AppError) -> JSONResponse:
    status_map = {
        "VALIDATION_ERROR": 422,
        "NOT_FOUND": 404,
        "UNAUTHORIZED": 403,
        "DATABASE_ERROR": 500,
    }
    status = status_map.get(exc.code, 500)
    return JSONResponse(
        status_code=status,
        content={
            "error": exc.code,
            "message": exc.message,
            "path": str(request.url),
        }
    )

@app.exception_handler(Exception)
async def generic_error_handler(request: Request, exc: Exception) -> JSONResponse:
    import logging
    logging.error(f"Unhandled error: {exc}", exc_info=True)
    return JSONResponse(
        status_code=500,
        content={"error": "INTERNAL_ERROR", "message": "An unexpected error occurred"}
    )

अपवाद समूह (पायथन 3.11+)

import asyncio

async def validate_all_fields(data: dict) -> dict:
    errors = []

    if not data.get("email"):
        errors.append(ValidationError("email", "required"))
    elif "@" not in data["email"]:
        errors.append(ValidationError("email", "invalid format"))

    if not data.get("name"):
        errors.append(ValidationError("name", "required"))

    if data.get("age") and (data["age"] < 13 or data["age"] > 120):
        errors.append(ValidationError("age", "must be between 13 and 120"))

    if errors:
        raise ExceptionGroup("Validation failed", errors)

    return data

# Handle exception groups
async def create_user(data: dict):
    try:
        validated = await validate_all_fields(data)
        return await db.users.create(validated)
    except* ValidationError as eg:
        # Handle only ValidationErrors from the group
        field_errors = {e.field: e.message for e in eg.exceptions}
        return {"errors": field_errors}
    except* DatabaseError as eg:
        for e in eg.exceptions:
            logger.error(f"DB error: {e}")
        raise

एक्सपोनेंशियल बैकऑफ़ के साथ पुनः प्रयास करें

import asyncio
import functools
import logging
from typing import Type

logger = logging.getLogger(__name__)

def async_retry(
    max_attempts: int = 3,
    delay: float = 1.0,
    backoff: float = 2.0,
    exceptions: tuple[Type[Exception], ...] = (Exception,),
    log_errors: bool = True,
):
    def decorator(func):
        @functools.wraps(func)
        async def wrapper(*args, **kwargs):
            last_error = None
            for attempt in range(1, max_attempts + 1):
                try:
                    return await func(*args, **kwargs)
                except asyncio.CancelledError:
                    raise  # never retry cancellation
                except exceptions as e:
                    last_error = e
                    if attempt == max_attempts:
                        break
                    wait = delay * (backoff ** (attempt - 1))
                    if log_errors:
                        logger.warning(
                            f"{func.__name__} attempt {attempt}/{max_attempts} failed: {e}. "
                            f"Retrying in {wait:.1f}s"
                        )
                    await asyncio.sleep(wait)
            raise last_error
        return wrapper
    return decorator

@async_retry(max_attempts=3, delay=0.5, exceptions=(ConnectionError, TimeoutError))
async def fetch_external_api(url: str) -> dict:
    async with httpx.AsyncClient() as client:
        r = await client.get(url, timeout=10)
        r.raise_for_status()
        return r.json()

प्रसंग-समृद्ध त्रुटि लॉगिंग

import structlog
import uuid
from contextvars import ContextVar

request_id_var: ContextVar[str] = ContextVar("request_id", default="")

# Configure structlog
structlog.configure(
    processors=[
        structlog.stdlib.filter_by_level,
        structlog.contextvars.merge_contextvars,
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.StackInfoRenderer(),
        structlog.processors.format_exc_info,
        structlog.processors.JSONRenderer(),
    ]
)

logger = structlog.get_logger()

async def process_order(order_id: str, user_id: str):
    # Bind context that appears in all logs from this request
    structlog.contextvars.bind_contextvars(
        request_id=str(uuid.uuid4()),
        order_id=order_id,
        user_id=user_id,
    )

    try:
        order = await db.orders.get(order_id)
        logger.info("order.fetched", amount=order["total"])

        payment = await payment_service.charge(order)
        logger.info("payment.success", transaction_id=payment["id"])

        return payment
    except PaymentError as e:
        logger.error("payment.failed", error_code=e.code, reason=str(e))
        raise
    except Exception as e:
        logger.exception("order.unexpected_error")
        raise

परिणाम प्रकार पैटर्न

from dataclasses import dataclass
from typing import TypeVar, Generic

T = TypeVar("T")
E = TypeVar("E", bound=Exception)

@dataclass
class Ok(Generic[T]):
    value: T
    success: bool = True

@dataclass
class Err(Generic[E]):
    error: E
    success: bool = False

Result = Ok[T] | Err[E]

async def safe_fetch_user(user_id: int) -> Result:
    try:
        user = await db.users.get(user_id)
        if not user:
            return Err(NotFoundError("User", user_id))
        return Ok(user)
    except DatabaseError as e:
        return Err(e)

# Usage - explicit handling, no try/except at call site
result = await safe_fetch_user(user_id)
if result.success:
    process(result.value)
else:
    handle_error(result.error)

2026 में पायथन त्रुटि प्रबंधन: डिज़ाइन अपवाद पदानुक्रम, बैच सत्यापन के लिए अपवाद समूहों का उपयोग, संदर्भ के साथ संरचित लॉगिंग लागू करना, टाइप किए गए रिट्री डेकोरेटर के साथ अविश्वसनीय संचालन को लपेटना। अपवादों को कभी भी चुपचाप न निगलें – खंड को छोड़कर प्रत्येक को या तो संभालना चाहिए, लॉग+रीराइज़ करना चाहिए, या रैप+रीराइज़ करना चाहिए।

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা