Modern Python 3.12+ చాప్టర్ 21 / 25 Phase 05: OOP & Advanced 2026 Edition

21. ఎక్సెప్షన్ హ్యాండ్లింగ్ & కస్టమ్ ఎర్రర్స్ (Robust Fault-Tolerant Code)

📌 Covered in this chapter: Errors vs Exceptions • Traceback Call Stack Anatomy • try-except-else-finally Suite • Standard Exception Hierarchy • raise & Exception Chaining • Custom Domain Exceptions • EAFP vs LBYL Philosophy • FinTech Resilient Gateway Capstone
మీరు ఒక ఆన్‌లైన్ పేమెంట్ యాప్ లేదా ఫ్లైట్ బుకింగ్ పోర్టల్‌ను వాడుతున్నప్పుడు, సర్వర్‌లో ఇంటర్నెట్ కనెక్షన్ పోయినా లేదా వినియోగదారుడు తప్పుడు పిన్ నంబర్ నమోదు చేసినా — యాప్ మొత్తం క్రాష్ అయిపోయి ఎర్రటి కోడ్ స్క్రీన్ కనిపిస్తే ఎంత అసౌకర్యంగా ఉంటుంది? ఒక బిగినర్ రాసే సాధారణ కోడ్‌కు మరియు ఒక సీనియర్ సాఫ్ట్‌వేర్ ఇంజనీర్ రూపొందించే ప్రొడక్షన్ కోడ్‌కు మధ్య ఉన్న అతిపెద్ద వ్యత్యాసం — ఎర్రర్లను తట్టుకునే శక్తి (Fault Tolerance & Resilience)! వాస్తవ ప్రపంచంలో ఊహించని సమస్యలు ఎప్పుడైనా రావచ్చు. సర్వర్ ఫైల్ తాత్కాలికంగా డిలీట్ కావచ్చు, జీరోతో భాగహారం జరగవచ్చు, లేదా డేటాబేస్ సర్వర్ బిజీగా మారవచ్చు. ఇటువంటి సంక్షోభ పరిస్థితులలో కూడా ప్రోగ్రామ్ కుప్పకూలిపోకుండా హుందాగా తట్టుకుని, యూజర్‌కు స్పష్టమైన సమాచారం అందించి డేటాను రక్షించే రక్షణ కవచమే ఎక్సెప్షన్ హ్యాండ్లింగ్ (Exception Handling). ఈ అధ్యాయంలో మనం పైథాన్ ఎర్రర్ ఆర్కిటెక్చర్, ట్రేస్‌బ్యాక్ విశ్లేషణ, try-except-else-finally నిర్మాణం, మరియు కస్టమ్ డొమైన్ ఎక్సెప్షన్ల ద్వారా తట్టుకునే శక్తి గల బ్యాంకింగ్ గేట్‌వేను సమగ్రంగా నిర్మిద్దాం.

1 ఎర్రర్ vs ఎక్సెప్షన్ — ప్రాథమిక వ్యత్యాసాలు & Traceback అనాటమీ

పైథాన్‌లో ప్రోగ్రామ్ ఆగిపోవడానికి గల కారణాలను కంప్యూటర్ సైన్స్ విభాగంలో మూడు విభిన్న వర్గాలుగా వర్గీకరిస్తారు. ఒక ఇంజనీర్‌గా ఈ మూడింటి స్వభావాన్ని ఖచ్చితంగా గుర్తించడం తప్పనిసరి:

ఎర్రర్ రకం ఎప్పుడు సంభవిస్తుంది? నివారణ లేదా హ్యాండ్లింగ్ మార్గం ఉదాహరణ
సింటాక్స్ ఎర్రర్ (Syntax Error) కోడ్ పార్సింగ్ సమయంలోనే (రన్ అవ్వకముందే) పైథాన్ వ్యాకరణ నియమాలు ఉల్లంఘించినప్పుడు. try-except ద్వారా క్యాచ్ చేయలేము! డెవలపర్ కోడ్‌ను సరిదిద్దాల్సిందే. if x == 5 (చివర కాలన్ : మర్చిపోవడం)
రన్‌టైమ్ ఎక్సెప్షన్ (Runtime Exception) సింటాక్స్ సరిగ్గా ఉన్నప్పటికీ ప్రోగ్రామ్ రన్ అవుతున్న సమయంలో ఊహించని డేటా లేదా పరిస్థితి ఎదురైనప్పుడు. try-except బ్లాక్స్ ద్వారా సంపూర్ణంగా హ్యాండిల్ చేసి ప్రోగ్రామ్‌ను రక్షించవచ్చు. 10 / 0 (ZeroDivision), ఫైల్ లభించకపోవడం
లాజికల్ బగ్ (Logical Bug) ప్రోగ్రామ్ ఎటువంటి ఎర్రర్ లేకుండా విజయవంతంగా నడుస్తుంది, కానీ తప్పుడు ఫలితాన్ని ఇస్తుంది. యూనిట్ టెస్ట్‌లు (pytest), కోడ్ రివ్యూలు మరియు డీబగ్గింగ్ ద్వారా సరిచేయాలి. డిస్కౌంట్ కూడాల్సింది పోయి తీసివేయడం

పైథాన్ Traceback ను ఎలా అర్థం చేసుకోవాలి? (Call Stack Unwinding):
పైథాన్‌లో అన్‌హ్యాండిల్డ్ ఎక్సెప్షన్ సంభవించినప్పుడు కన్సోల్‌లో కనిపించే ఎర్రర్ సందేశాన్ని Traceback అంటారు. ఇది కేవలం ఎర్రర్ మాత్రమే కాదు; ప్రోగ్రామ్ ఏయే ఫంక్షన్లను పిలుస్తూ ఆ చివరి ప్రమాదకర లైన్ వరకు చేరుకుందో వివరించే పూర్తి హిస్టరీ రికార్డ్!

🔍 ట్రేస్‌బ్యాక్ చదివే బంగారు నియమం (Bottom-Up Rule):
ఎల్లప్పుడూ ట్రేస్‌బ్యాక్‌ను అట్టడుగు లైన్ నుండి పైకి చదవాలి! చిట్టచివరి లైన్ ఎర్రర్ పేరును మరియు అసలు కారణాన్ని (ఉదా: KeyError: 'coupon_code') సూటిగా ప్రకటిస్తుంది. దాని పైభాగంలో ఉన్న లైన్లు ఏ ఫైల్‌లో, ఏ లైన్ నంబర్ వద్ద, ఏ ఫంక్షన్ కాల్ వల్ల సమస్య వచ్చిందో స్టాక్ ఫ్రేమ్ క్రమంలో వివరిస్తాయి.

2 try-except బ్లాక్ ఆర్కిటెక్చర్ & Anti-Patterns

పైథాన్ వర్చువల్ మెషీన్ (PVM) లో try బ్లాక్ అనేది ఒక భద్రతా వలయం వంటిది. try బ్లాక్ లోపల ఎగ్జిక్యూషన్ జరుగుతున్నప్పుడు ఏదైనా ఎక్సెప్షన్ సంభవిస్తే, PVM సాధారణ సీక్వెన్షియల్ ఎగ్జిక్యూషన్‌ను తక్షణమే నిలిపివేసి, సరిపోయే except బ్లాక్ కోసం కాల్ స్టాక్‌లో శోధిస్తుంది:

⚠️ ప్రమాదకరమైన "The Bare Except Anti-Pattern":

సాఫ్ట్‌వేర్ పరిశ్రమలో బిగినర్స్ చేసే అత్యంత ప్రమాదకరమైన తప్పు: ఎటువంటి క్లాస్ పేరు పేర్కొనకుండా కేవలం except: pass అని గుడ్డిగా రాయడం. దీనిని "ఎర్రర్లను మింగివేయడం" (Swallowing Exceptions) అంటారు.

  • ఇది వినియోగదారుడు ప్రోగ్రామ్‌ను ఆపడానికి కీబోర్డ్‌పై నొక్కే Ctrl+C (KeyboardInterrupt) ని కూడా నిరోధిస్తుంది!
  • సిస్టమ్ మెమరీ అయిపోయినప్పుడు వచ్చే MemoryError మరియు SystemExit లను సైలెంట్‌గా కప్పిపుచ్చుతుంది.
  • దీనివల్ల ప్రొడక్షన్ సర్వర్‌లో డేటాబేస్ కరప్ట్ అయినా లాగ్ ఫైల్స్‌లో ఎటువంటి ఆధారాలు కనిపించక డీబగ్గింగ్ పీడకలగా మారుతుంది.

3 బహుళ ఎక్సెప్షన్లను హ్యాండిల్ చేయడం (Multiple & Grouped)

ఒకే ఆపరేషన్ వేర్వేరు సందర్భాలలో విభిన్న రకాల వైఫల్యాలకు గురికావచ్చు. ఉదాహరణకు ఒక వినియోగదారుడి సమాచారాన్ని ప్రాసెస్ చేస్తున్నప్పుడు: నంబర్ బదులు అక్షరాలు ఇస్తే ValueError రావచ్చు, సున్నాతో భాగిస్తే ZeroDivisionError రావచ్చు, లేదా డిక్షనరీలో కీ లేకపోతే KeyError రావచ్చు.

పద్ధతి సింటాక్స్ నమూనా వాడాల్సిన సరైన సందర్భం
వేర్వేరు Except బ్లాక్స్ except ValueError:
except KeyError:
ప్రతి ఎర్రర్‌కు భిన్నమైన రికవరీ లాజిక్ లేదా యూజర్ సందేశం ఉన్నప్పుడు.
గ్రూప్డ్ ఎక్సెప్షన్స్ (Tuple) except (TypeError, ValueError) as err: బహుళ ఎర్రర్లకు ఒకే విధమైన లాగింగ్ లేదా ప్రత్యామ్నాయ డీఫాల్ట్ విలువ వర్తించినప్పుడు.
ఎక్సెప్షన్ అలియాస్ (as) except ZeroDivisionError as zde: ఎక్సెప్షన్ ఆబ్జెక్ట్ లోపల ఉన్న అసలు ఎర్రర్ మెసేజ్‌ను లాగ్ ఫైల్‌లోకి రాయాల్సి వచ్చినప్పుడు.

4 The else బ్లాక్ యొక్క ప్రాముఖ్యత (Clean Code Architecture)

పైథాన్‌లో చాలామందికి తెలియని, కానీ ప్రొఫెషనల్ సాఫ్ట్‌వేర్ ఆర్కిటెక్చర్‌లో అమితంగా వాడే ఫీచర్ try-else నిర్మాణం. try బ్లాక్‌లో ఎటువంటి లోపం రానప్పుడు మాత్రమే ఎగ్జిక్యూట్ అవ్వాల్సిన కోడ్‌ను else బ్లాక్‌లో ఉంచుతాము.

ఈ కోడ్‌ను try లోనే నేరుగా రాయవచ్చు కదా? else ఎందుకు?

ఒక ప్రొఫెషనల్ నియమం: "Keep your try blocks as small as possible" (ట్రై బ్లాక్ లోపల కేవలం ప్రమాదం జరిగే అవకాశం ఉన్న 1 లేదా 2 లైన్లను మాత్రమే ఉంచాలి). ఒకవేళ మిగిలిన లాజిక్‌ను కూడా try లోపలే ఉంచితే, ఆ తర్వాత లైన్లలో ఊహించని విధంగా వచ్చిన మరొక బగ్‌ను కూడా మన except బ్లాక్ పొరపాటున క్యాచ్ చేసి, తప్పుడు ఎర్రర్ మెసేజ్ చూపించే ప్రమాదం ఉంది. else వాడటం వల్ల ట్రై బ్లాక్ స్కోప్ క్లీన్‌గా మరియు సురక్షితంగా ఉంటుంది.

5 The finally బ్లాక్ — గ్యారెంటీడ్ క్లీనప్ (Resource Safety)

ఆపరేటింగ్ సిస్టమ్‌లో ఫైళ్లు, డేటాబేస్ కనెక్షన్లు, మరియు నెట్‌వర్క్ సాకెట్లు వంటి వనరులు (System Resources) పరిమితంగా ఉంటాయి. ఒక ప్రోగ్రామ్ ఫైల్‌ను ఓపెన్ చేసిన తర్వాత ఎర్రర్ వచ్చి మధ్యలోనే ఆగిపోతే, ఆ ఫైల్ మెమరీలోనే లాక్ అయి ఉండిపోతుంది (Resource Leak). ఇటువంటి ప్రమాదాలను నివారించడానికి రూపొందించిన రక్షక కవచమే finally:

6 ఎక్సెప్షన్లను విసరడం: raise కీవర్డ్

పైథాన్ కేవలం అంతర్నిర్మిత లోపాలపైనే కాకుండా, మీ బిజినెస్ నిబంధనలు (Domain Business Logic) ఉల్లంఘించబడినప్పుడు మీ స్వంతంగా హెచ్చరికలను జారీ చేయడానికి raise కీవర్డ్‌ను అందిస్తుంది. ఉదాహరణకు యూజర్ వయస్సు నెగెటివ్‌గా ఉండటం, బ్యాంక్ అకౌంట్ బ్యాలెన్స్ కంటే ఎక్కువ డ్రా చేయాలని చూడటం వంటివి పైథాన్ సింటాక్స్ పరంగా సరైనవే అయినప్పటికీ వ్యాపార పరంగా తప్పులు. అటువంటి సమయాల్లో స్పష్టమైన సందేశంతో ఎక్సెప్షన్‌ను విసిరి పై స్థాయి కాలింగ్ కోడ్‌ను అప్రమత్తం చేస్తాము.

7 కోడ్ డెమో 1: లైవ్ బ్యాంకింగ్ ఫండ్ ట్రాన్స్‌ఫర్ with Full Suite

try-except-else-finally యొక్క పూర్తి సమగ్ర ప్రవర్తనను క్రింది కోడ్‌లో పరిశీలిద్దాం:

01_banking_exception_suite.py
# =====================================================================
# చాప్టర్ 21 డెమో 1: try - except - else - finally ఆర్కిటెక్చర్
# =====================================================================

def transfer_funds(sender_bal: float, amount: float):
    print(f"
--- లావాదేవీ ప్రారంభం: మొత్తం ₹{amount:,.2f} ---")
    connection_open = True
    print("🔌 బ్యాంకింగ్ సెక్యూర్ గేట్‌వే కనెక్ట్ చేయబడింది.")

    try:
        if amount <= 0:
            raise ValueError("బదిలీ మొత్తం ₹0 కంటే ఎక్కువ ఉండాలి!")
        if amount > sender_bal:
            raise ArithmeticError("ఖాతాలో తగినంత నగదు నిల్వ లేదు!")

        new_balance = sender_bal - amount

    except ValueError as ve:
        print(f"❌ ఇన్‌పుట్ లోపం: {ve}")
    except ArithmeticError as ae:
        print(f"❌ బ్యాంకింగ్ నిల్వ లోపం: {ae}")
    else:
        # ఎర్రర్ రాకపోతేనే ఎగ్జిక్యూట్ అవుతుంది!
        print(f"✅ లావాదేవీ విజయవంతం! తాజా బ్యాలెన్స్: ₹{new_balance:,.2f}")
    finally:
        # ఎర్రర్ వచ్చినా రాకపోయినా ఖచ్చితంగా రన్ అవుతుంది!
        connection_open = False
        print("🔒 సెక్యూర్ గేట్‌వే కనెక్షన్ క్లోజ్ చేయబడింది (Cleaned up).")

# టెస్ట్ 1: విజయవంతమైన బదిలీ
transfer_funds(50000.0, 15000.0)

# టెస్ట్ 2: తగినంత నిల్వ లేని సందర్భం
transfer_funds(10000.0, 25000.0)

8 పైథాన్ స్టాండర్డ్ ఎక్సెప్షన్స్ హైరార్కీ (The Hierarchy Reference)

పైథాన్‌లో అన్ని ఎక్సెప్షన్లు సాధారణ ఫంక్షన్లు కావు; అవి ఆబ్జెక్ట్ ఓరియెంటెడ్ క్లాస్ వంశవృక్షాన్ని (Inheritance Hierarchy) కలిగి ఉంటాయి:

🌳 పైథాన్ ఎక్సెప్షన్ ట్రీ (Family Tree):

  • BaseException: పైథాన్‌లోని అన్ని ఎర్రర్లకు పరమోన్నత మూల క్లాస్. దీని క్రింద సిస్టమ్-లెవల్ ఈవెంట్లు ఉంటాయి:
    • SystemExit — ప్రోగ్రామ్ ముగింపు సంకేతం.
    • KeyboardInterrupt — యూజర్ కీబోర్డ్ ద్వారా ప్రోగ్రామ్‌ను ఆపినప్పుడు వస్తుంది.
    • Exception: సాధారణ అప్లికేషన్ మరియు డెవలపర్ ఎర్రర్లన్నింటికీ మూల క్లాస్. మన అప్లికేషన్లలో క్యాచ్ చేయాల్సింది కేవలం దీనిని మాత్రమే!
  • Exception నుండి ఉద్భవించిన ముఖ్యమైన బ్రాంచీలు:
    • ArithmeticError ➔ ZeroDivisionError (సున్నాతో భాగహారం), OverflowError (సంఖ్యా పరిమితి దాటిపోవడం)
    • LookupError ➔ IndexError (లిస్ట్ పరిధి దాటిన ఇండెక్స్), KeyError (డిక్షనరీలో లేని కీ)
    • ValueError — సరైన డేటా టైప్ అయినప్పటికీ విలువ చెల్లనప్పుడు (ఉదా: int("abc"))
    • TypeError — అనుకూలం కాని డేటా రకాలపై ఆపరేషన్ చేసినప్పుడు (ఉదా: "హలో" + 5)
    • OSError ➔ FileNotFoundError (ఫైల్ లేకపోవడం), PermissionError (యాక్సెస్ లేకపోవడం)

9 ఎక్సెప్షన్ చైనింగ్ (Exception Chaining with raise ... from)

పెద్ద మైక్రోసర్వీస్ అప్లికేషన్లలో లో-లెవల్ ఎర్రర్‌ను క్యాచ్ చేసి, బయటి క్లయింట్‌కు అర్థమయ్యే హై-లెవల్ బిజినెస్ ఎర్రర్‌గా మార్చాల్సి ఉంటుంది. పైథాన్ 3 లో PEP 3134 ద్వారా ప్రవేశపెట్టబడిన Exception Chaining అసలైన మూలకారణం (Root Cause) మరుగున పడకుండా భద్రపరుస్తుంది:

10 కస్టమ్ డొమైన్ ఎక్సెప్షన్స్ సృష్టి & ఎంటర్‌ప్రైజ్ ఆర్కిటెక్చర్

ఎంటర్‌ప్రైజ్ సాఫ్ట్‌వేర్‌లో సాధారణ పైథాన్ ఎర్రర్ల (ValueError, KeyError) తో సరిపెట్టలేము. ప్రతి డొమైన్‌కు (FinTech, E-Commerce, Healthcare) ప్రత్యేకమైన ఎక్సెప్షన్ హైరార్కీ ఉండాలి:

కస్టమ్ ఎక్సెప్షన్ క్లాస్ డిజైన్ బెస్ట్ ప్రాక్టీసెస్:

  1. ఎల్లప్పుడూ Exception ను మాత్రమే ఇన్హెరిట్ చేయాలి (ఎట్టి పరిస్థితుల్లోనూ BaseException ను ఇన్హెరిట్ చేయకూడదు).
  2. ప్రాజెక్ట్‌కు ఒక బేస్ ఎక్సెప్షన్ క్లాస్ ఉండాలి: ఉదాహరణకు class AppBaseException(Exception): pass. దీనివల్ల క్లయింట్లు ప్రాజెక్ట్‌లోని ఏ ఎర్రర్‌నైనా ఒకే ఒక క్లాస్ ద్వారా క్యాచ్ చేయగలుగుతారు.
  3. అదనపు మెటాడేటాను భద్రపరచండి: కేవలం స్ట్రింగ్ మెసేజ్ మాత్రమే కాకుండా, HTTP స్టేటస్ కోడ్ (404, 401), ఎర్రర్ కోడ్ (ORDER_OUT_OF_STOCK), మరియు టైమ్‌స్టాంప్‌లను అట్రిబ్యూట్‌లుగా భద్రపరచడం ద్వారా ఆటోమేటెడ్ మానిటరింగ్ టూల్స్‌కు డేటా సులభంగా అందుతుంది.

11 కోడ్ డెమో 2: ఇ-కామర్స్ ఇన్వెంటరీ కార్ట్ with Custom Exceptions

కస్టమ్ ఎక్సెప్షన్లతో కూడిన స్టాక్ మరియు బ్యాలెన్స్ వాలిడేషన్ సిస్టమ్‌ను పరిశీలిద్దాం:

02_custom_ecommerce_exceptions.py
# కస్టమ్ ఎక్సెప్షన్ క్లాసెస్
class OutOfStockError(Exception):
    """ఉత్పత్తి నిల్వ లేనప్పుడు వచ్చే ఎర్రర్."""
    pass

class InsufficientBalanceError(Exception):
    """యూజర్ వాలెట్‌లో తగినంత నగదు లేనప్పుడు వచ్చే ఎర్రర్."""
    pass

def checkout_order(item_name: str, requested_qty: int, available_stock: int, total_price: float, wallet_bal: float):
    if requested_qty > available_stock:
        raise OutOfStockError(f"క్షమించండి! '{item_name}' స్టాక్ కేవలం {available_stock} మాత్రమే ఉంది.")
    if total_price > wallet_bal:
        shortfall = total_price - wallet_bal
        raise InsufficientBalanceError(f"వాలెట్‌లో ₹{shortfall:,.2f} తక్కువగా ఉంది!")

    print(f"🎉 ఆర్డర్ కన్ఫర్మ్ అయింది! వస్తువు: {item_name} (పరిమాణం: {requested_qty})")

# టెస్టింగ్
try:
    checkout_order("స్మార్ట్‌ఫోన్", requested_qty=3, available_stock=1, total_price=45000, wallet_bal=50000)
except OutOfStockError as ose:
    print(f"🚨 ఇన్వెంటరీ హెచ్చరిక: {ose}")
except InsufficientBalanceError as ibe:
    print(f"🚨 పేమెంట్ హెచ్చరిక: {ibe}")

12 కామన్ బిగినర్స్ మిస్టేక్స్ & ప్రొడక్షన్ బెస్ట్ ప్రాక్టీసెస్: EAFP vs LBYL

పైథాన్‌లో ఎక్సెప్షన్ హ్యాండ్లింగ్ కేవలం ఎర్రర్లను నివారించడానికి మాత్రమే కాదు; ప్రోగ్రామింగ్ శైలిని (Design Philosophy) తీర్చిదిద్దే అత్యంత ప్రముఖమైన సిద్ధాంతం. ఇతర భాషల్లో (C, Java) సాధారణంగా LBYL (Look Before You Leap) శైలిని ఉపయోగిస్తారు, కానీ పైథాన్‌లో ఆధునిక నిపుణులు EAFP (Easier to Ask for Forgiveness than Permission) శైలికి ప్రాధాన్యత ఇస్తారు:

ఫీచర్ LBYL (Look Before You Leap) EAFP (Easier to Ask Forgiveness)
ఫిలాసఫీ పనిని ప్రారంభించే ముందే ప్రతి చిన్న కండిషన్‌ను if-else తో పదే పదే తనిఖీ చేయడం. సానుకూల అంచనాతో పనిని నేరుగా ప్రయత్నించడం (try), అరుదుగా పొరపాటు జరిగితే క్షమించమని అడగడం (except).
వేగం & పనితీరు ప్రతిసారీ అదనపు కండిషనల్ లుకప్ ఖర్చు అవుతుంది (ఉదా: key in dict తర్వాత మళ్లీ dict[key]). సాధారణ కేసులలో ఎటువంటి అదనపు ఓవర్‌హెడ్ లేకుండా చాలా వేగంగా రన్ అవుతుంది.
రేస్ కండిషన్ భద్రత TOCTOU (Time of Check to Time of Use) రేస్ కండిషన్ ఏర్పడే ప్రమాదం ఉంది (మనం ఫైల్ ఉందో లేదో చెక్ చేసిన క్షణంలోనే మరొక ప్రాసెస్ దానిని డిలీట్ చేయవచ్చు). నేరుగా ఆపరేషన్‌ను అమలు చేయడం వల్ల రేస్ కండిషన్లను సహజంగానే నివారిస్తుంది.

13 రియల్-వరల్డ్ ప్రాజెక్ట్: "Enterprise FinTech Payment Gateway & Resilient Engine"

ఈ ఇరవై ఒకటవ అధ్యాయంలో నేర్చుకున్న అన్ని ఎక్సెప్షన్ కాన్సెప్టులను (try-except-else-finally, కస్టమ్ డొమైన్ ఎక్సెప్షన్లు, ఎక్సెప్షన్ చైనింగ్, ఆటోమేటిక్ రీట్రై లాజిక్, సేఫ్ రోల్‌బ్యాక్) అనుసంధానిస్తూ — విఫలమైన లావాదేవీలను సురక్షితంగా రికవర్ చేసే పూర్తి స్థాయి FinTech Resilient Payment Gateway Engine ను నిర్మిద్దాం!

03_fintech_payment_gateway_engine.py
# =====================================================================
# చాప్టర్ 21 మినీ ప్రాజెక్ట్: FinTech Resilient Payment Gateway Engine
# కాన్సెప్ట్స్: try-except-else-finally, Custom Domain Exceptions,
#             Retry Logic, Circuit Breaker Basics, Audit Logging
# =====================================================================
import time

# 1. కస్టమ్ బ్యాంకింగ్ ఎక్సెప్షన్ క్లాసెస్
class PaymentException(Exception):
    """అన్ని పేమెంట్ వైఫల్యాలకు బేస్ క్లాస్."""
    pass

class CardExpiredError(PaymentException):
    pass

class InsufficientFundsError(PaymentException):
    pass

class NetworkGatewayTimeoutError(PaymentException):
    pass

class FinTechPaymentProcessor:
    def __init__(self, merchant_id: str):
        self.merchant_id = merchant_id
        self.audit_log = []

    def log_event(self, txn_id: str, status: str, message: str):
        entry = {
            "txn_id": txn_id,
            "status": status,
            "message": message,
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
        }
        self.audit_log.append(entry)

    def authorize_card(self, card_number: str, expiry_year: int) -> bool:
        if expiry_year < 2026:
            raise CardExpiredError("కార్డ్ గడువు ముగిసింది! దయచేసి చెల్లుబాటు అయ్యే కార్డును ఉపయోగించండి.")
        return True

    def deduct_balance(self, current_balance: float, amount: float) -> float:
        if amount > current_balance:
            shortfall = amount - current_balance
            raise InsufficientFundsError(f"ఖాతాలో సరిపడా నిల్వ లేదు! కొరత: ₹{shortfall:,.2f}")
        return current_balance - amount

    def simulate_bank_network_call(self, attempt_number: int):
        # 1వ ప్రయత్నంలో నెట్‌వర్క్ ఫెయిల్యూర్ సిమ్యులేషన్
        if attempt_number == 1:
            raise NetworkGatewayTimeoutError("బ్యాంక్ సర్వర్ నుండి రెస్పాన్స్ రాలేదు (HTTP 504 Timeout)")
        return True

    def process_transaction(self, txn_id: str, card_no: str, exp_year: int, balance: float, amount: float):
        print(f"
==================================================")
        print(f"💳 ప్రాసెసింగ్ లావాదేవీ: {txn_id} (మొత్తం: ₹{amount:,.2f})")
        print(f"==================================================")
        
        session_active = True
        try:
            # దశ 1: కార్డ్ వ్యాలిడేషన్
            self.authorize_card(card_no, exp_year)

            # దశ 2: బ్యాలెన్స్ తనిఖీ & డిడక్షన్
            new_bal = self.deduct_balance(balance, amount)

            # దశ 3: ఆటోమేటిక్ రీట్రైతో కూడిన నెట్‌వర్క్ కాల్
            max_retries = 2
            for attempt in range(1, max_retries + 1):
                try:
                    print(f"  📡 బ్యాంక్ గేట్‌వేకు కనెక్ట్ అవుతోంది (ప్రయత్నం {attempt}/{max_retries})...")
                    self.simulate_bank_network_call(attempt)
                    break
                except NetworkGatewayTimeoutError as nte:
                    print(f"  ⚠️ హెచ్చరిక: {nte}")
                    if attempt == max_retries:
                        raise  # రీట్రైలు ముగిస్తే బయట except కి పంపడం

        except CardExpiredError as cee:
            self.log_event(txn_id, "FAILED", f"కార్డ్ ఎక్స్‌పైరీ లోపం: {cee}")
            print(f"❌ లావాదేవీ విఫలం: {cee}")
        except InsufficientFundsError as ife:
            self.log_event(txn_id, "FAILED", f"నిధుల కొరత: {ife}")
            print(f"❌ లావాదేవీ విఫలం: {ife}")
        except NetworkGatewayTimeoutError as nge:
            self.log_event(txn_id, "RETRY_EXHAUSTED", "నెట్‌వర్క్ టైమ్‌అవుట్ కారణంగా విఫలమైంది")
            print(f"🚨 క్రిటికల్ ఎర్రర్: గేట్‌వే అందుబాటులో లేదు. నగదు కట్ కాలేదు.")
        except Exception as unk:
            self.log_event(txn_id, "CRITICAL", f"ఊహించని లోపం: {unk}")
            print(f"💥 అన్‌ఎక్స్‌పెక్టెడ్ సిస్టమ్ ఎర్రర్: {unk}")
        else:
            # ఎటువంటి ఎర్రర్ రాకపోతేనే ఎగ్జిక్యూట్ అవుతుంది!
            self.log_event(txn_id, "SUCCESS", f"విజయవంతంగా పూర్తయింది. మిగిలిన బ్యాలెన్స్: ₹{new_bal:,.2f}")
            print(f"✅ లావాదేవీ విజయవంతం! మర్చంట్: {self.merchant_id}")
            print(f"💰 కస్టమర్ తాజా బ్యాలెన్స్: ₹{new_bal:,.2f}")
        finally:
            # సెషన్ క్లీనప్
            session_active = False
            print(f"🔒 [AUDIT] సెక్యూర్ సెషన్ క్లోజ్ చేయబడింది. ఆడిట్ లాగ్ అప్‌డేట్ అయింది.")


# =====================================================================
# సిస్టమ్ టెస్టింగ్ డ్రైవర్
# =====================================================================
processor = FinTechPaymentProcessor(merchant_id="TELUGU_PAY_MERCHANT_007")

# కేస్ 1: కార్డ్ గడువు ముగిసిన కేసు
processor.process_transaction("TXN_1001", "4532-XXXX-XXXX-8901", exp_year=2024, balance=50000, amount=4500)

# కేస్ 2: సరిపడా బ్యాలెన్స్ లేని కేసు
processor.process_transaction("TXN_1002", "4532-XXXX-XXXX-8901", exp_year=2028, balance=2000, amount=8500)

# కేస్ 3: మొదటిసారి ఫెయిల్ అయి ఆటో-రీట్రైతో సక్సెస్ అయ్యే కేసు
processor.process_transaction("TXN_1003", "4532-XXXX-XXXX-8901", exp_year=2029, balance=75000, amount=12000)

# పూర్తి ఆడిట్ లాగ్ ప్రింట్ చేయడం
print("
" + "=" * 55)
print("📊 FINTECH AUDIT TRAIL LOGS:")
print("=" * 55)
for log in processor.audit_log:
    print(f"• [{log['timestamp']}] {log['txn_id']} | {log['status']} | {log['message']}")
print("=" * 55)

? మీ అవగాహనను పరీక్షించుకోండి (5 Interactive Quizzes)

1. SyntaxError ను try-except బ్లాక్ ద్వారా క్యాచ్ చేయగలమా?
సమాధానం: క్యాచ్ చేయలేము! సింటాక్స్ ఎర్రర్ అనేది కోడ్ రన్ అవ్వడానికి ముందే (Parsing Phase లో) పైథాన్ కంపైలర్ ద్వారా గుర్తించబడుతుంది. రన్‌టైమ్ ఎక్సెప్షన్లను మాత్రమే try-except ద్వారా క్యాచ్ చేయగలం.
2. try బ్లాక్‌లో else బ్లాక్ ఎప్పుడు ఎగ్జిక్యూట్ అవుతుంది?
సమాధానం: try బ్లాక్ లోపల ఎటువంటి ఎక్సెప్షన్ రాని సందర్భంలో మాత్రమే else బ్లాక్ అమలు అవుతుంది. ఏదైనా ఎర్రర్ వస్తే else అమలు కాదు.
3. BaseException మరియు Exception మధ్య తేడా ఏమిటి?
సమాధానం: BaseException అనేది పైథాన్‌లోని అన్ని ఎర్రర్లకు మూల క్లాస్ (ఇందులో KeyboardInterrupt, SystemExit ఉంటాయి). Exception అనేది సాధారణ అప్లికేషన్ ఎర్రర్లకు మూల క్లాస్. మన కోడ్‌లో ఎల్లప్పుడూ Exception ను మాత్రమే క్యాచ్ చేయాలి.
4. raise ... from None ఎప్పుడు ఉపయోగిస్తారు?
సమాధానం: ఒక కొత్త ఎక్సెప్షన్‌ను విసిరినప్పుడు దాని అసలైన మునుపటి అంతర్గత ఎర్రర్ ట్రేస్‌బ్యాక్‌ను దాచిపెట్టడానికి (ఉదాహరణకు అంతర్గత డేటాబేస్ పాస్‌వర్డ్‌లు లేదా కాన్ఫిడెన్షియల్ సర్వర్ వివరాలు యూజర్‌కు కనిపించకుండా) raise ... from None వాడతారు.
5. finally బ్లాక్‌లో return స్టేట్‌మెంట్ రాయకూడదు ఎందుకు?
సమాధానం: finally లో return రాస్తే, try లేదా except లో వచ్చిన ఒరిజినల్ రిటర్న్ వాల్యూ లేదా రేజ్ అయిన ఎక్సెప్షన్ పూర్తిగా అణచివేయబడి రద్దు అవుతుంది.
← మునుపటి అధ్యాయం: 20. ఫైల్ హ్యాండ్లింగ్ & JSON తర్వాతి అధ్యాయం: 22. OOP బేసిక్స్ (Classes & Objects) →

ఈ FinTech Resilient Engine ని లైవ్‌గా మన కంపైలర్‌లో రన్ చేయండి!

ఎటువంటి లోకల్ సెటప్ లేకుండా, బ్రౌజర్‌లోనే Modern Python 3 కంపైలర్‌లో ఈ కోడ్‌ను ఎగ్జిక్యూట్ చేసి అవుట్‌పుట్ తనిఖీ చేయండి.