24. అడ్వాన్స్డ్ పైథాన్ — డెకరేటర్లు, జెనరేటర్లు & డండర్ మెథడ్స్
1 ఫస్ట్-క్లాస్ ఫంక్షన్స్ (First-Class Functions) & క్లోజర్స్ (Closures)
పైథాన్లో డెకరేటర్లను అర్థం చేసుకోవాలంటే, మొదట ఫంక్షన్లను పైథాన్ ఎలా చూస్తుందో అర్థం చేసుకోవాలి. పైథాన్లో ఫంక్షన్లు First-Class Citizens:
- ఫంక్షన్ను ఒక వేరియబుల్కు అసైన్ చేయవచ్చు (
my_func = print). - ఫంక్షన్ను మరొక ఫంక్షన్కు ఆర్గ్యుమెంట్గా పాస్ చేయవచ్చు.
- ఒక ఫంక్షన్ లోపల మరొక ఇన్నర్ ఫంక్షన్ను డిఫైన్ చేసి, ఆ ఇన్నర్ ఫంక్షన్నే రిటర్న్ చేయవచ్చు!
క్లోజర్ (Closure) మెకానిక్స్ & Free Variables:
ఒక ఔటర్ ఫంక్షన్ ఎగ్జిక్యూషన్ ముగిసిపోయి, దాని లోకల్ స్కోప్ మెమరీ నుండి తుడిచిపెట్టుకుపోయిన తర్వాత కూడా — దాని లోపల ఉన్న ఇన్నర్ ఫంక్షన్ ఆ ఔటర్ స్కోప్ యొక్క వేరియబుల్స్ను (Free Variables) గుర్తుంచుకునే అద్భుతమైన సామర్థ్యాన్ని క్లోజర్ అంటారు.
పైథాన్ అంతర్గతంగా ప్రతి ఇన్నర్ ఫంక్షన్ ఆబ్జెక్ట్కు __closure__ అనే ట్యూపుల్ను జతచేస్తుంది. ఇందులో సెల్ ఆబ్జెక్టుల (Cell Objects) రూపంలో ఔటర్ వేరియబుల్స్ భద్రంగా నిల్వ ఉంటాయి. డెకరేటర్లు పనిచేయడానికి సరిగ్గా ఈ క్లోజర్ మెకానిజమే అత్యంత కీలకమైన పునాది!
2 ఫంక్షన్ డెకరేటర్ల నిర్మాణం (Decorators Anatomy & @ Syntax)
ఒక ఫంక్షన్ యొక్క అసలు సోర్స్ కోడ్ను ఎటువంటి మార్పు చేయకుండా, దాని ముందు లేదా వెనుక అదనపు ఫంక్షనాలిటీని (ఉదా: Logging, Timing, Authentication) చేర్చే హైయర్-ఆర్డర్ ఫంక్షన్ను డెకరేటర్ (Decorator) అంటారు:
మీరు ఒక ఫంక్షన్ పైన
@my_decorator అని రాసినప్పుడు, పైథాన్ ఇంటర్ప్రీటర్ కోడ్ లోడ్ అయ్యే సమయంలోనే ఆటోమేటిక్గా original_func = my_decorator(original_func) గా రీరైట్ చేస్తుంది! అంటే డెకరేటర్ అనేది అసలు ఫంక్షన్ను ఇన్పుట్గా తీసుకుని, అదనపు రక్షణ లేదా లాజిక్ జోడించిన ఒక కొత్త "ర్యాపర్ ఫంక్షన్" ను రిటర్న్ చేస్తుంది.
3 functools.wraps ప్రాముఖ్యత (Metadata Preservation)
ఒక ఫంక్షన్ను ర్యాప్ చేసినప్పుడు, దాని పేరు (__name__) మరియు డాక్యుమెంటేషన్ (__doc__) ర్యాపర్ ఫంక్షన్ పేరుతో రీప్లేస్ అయిపోతాయి. దీనివల్ల డీబగ్గింగ్, డాక్యుమెంటేషన్ జనరేటర్లు (Sphinx), మరియు వెబ్ ఫ్రేమ్వర్కులు (Flask/FastAPI) తీవ్రంగా గందరగోళానికి గురవుతాయి:
- సమస్య:
@my_decoratorవాడిన తర్వాతprint(my_function.__name__)చేస్తే, అసలు పేరుకు బదులుగా'wrapper'అని కనిపిస్తుంది. - పరిష్కారం: ర్యాపర్ ఫంక్షన్ పైన
@functools.wraps(func)ను చేర్చడం. ఇది అసలు ఫంక్షన్ యొక్క__name__,__doc__,__module__, మరియు__annotations__లను కొత్త ర్యాపర్పైకి సురక్షితంగా కాపీ చేస్తుంది. అందువల్ల ప్రతి ప్రొడక్షన్ డెకరేటర్లో@wrapsవాడటం తప్పనిసరి ప్రమాణం!
4 పారామీటర్లతో కూడిన డెకరేటర్లు & క్లాస్ బేస్డ్ డెకరేటర్లు (__call__)
డెకరేటర్కు ఆర్గ్యుమెంట్లను పాస్ చేయాలంటే (ఉదా: @repeat(num_times=3) లేదా @role_required("ADMIN")), మనం 3 స్థాయిల నెస్టెడ్ ఫంక్షన్లను (Triple-nested functions: Decorator Factory ➔ Decorator ➔ Wrapper) ఉపయోగించాలి:
క్లాస్ బేస్డ్ డెకరేటర్లు (Stateful Decorators) & Enterprise Patterns:
డెకరేటర్ను ఫంక్షన్గా మాత్రమే కాకుండా ఒక పూర్తి క్లాస్గా కూడా రూపొందించవచ్చు. ఒక క్లాస్ ఆబ్జెక్ట్ను ఫంక్షన్ లాగా కాల్ చేయడానికి (Callable Object) పైథాన్లో __call__ డండర్ మెథడ్ను వాడుతాము.
ఒక ఫంక్షన్ ఎన్నిసార్లు పిలవబడిందో లెక్కించడానికి (Call Counter), లేదా ఫలితాలను క్యాష్ చేయడానికి (Memoization) క్లాస్ అట్రిబ్యూట్లు చాలా శక్తివంతమైన సాధనాలు. __init__ లో అసలు ఫంక్షన్ను దాచిపెట్టి, __call__ లో ప్రతి కాల్ను ట్రాక్ చేస్తాము.
రియల్-వరల్డ్ వెబ్ డెవలప్మెంట్లో పాపులర్ డెకరేటర్ల సూట్:
@login_required(Authentication): వెబ్ అభ్యర్థనను యూజర్ పంపినప్పుడు సెషన్ టోకెన్ లేదా కుకీని చెక్ చేసి, యూజర్ లాగిన్ అయి ఉంటేనే అసలు వ్యూ ఫంక్షన్ను పిలవడం.@rate_limit(requests=60, window_sec=60)(API Throttling): ఒక ఐపీ అడ్రస్ నుండి నిమిషానికి 60 రిక్వెస్టుల కంటే ఎక్కువ వస్తే 429 Too Many Requests తో బ్లాక్ చేయడం.@cache_response(ttl_seconds=300)(Caching): పదే పదే మారే అవకాశం లేని డేటాబేస్ ఫలితాలను Redis లో క్యాష్ చేసి రెస్పాన్స్ సమయాన్ని 200ms నుండి 2ms కి తగ్గించడం!
5 ఇటరేటర్ ప్రోటోకాల్ (The Python Iterator Protocol)
పైథాన్లో for item in collection: లూప్ తెరవెనుక ఎలా పనిచేస్తుంది? దీని వెనుక పైథాన్ యొక్క అధికారిక Iterator Protocol ఉంది:
- Iterable (ఇటరబుల్):
__iter__()మెథడ్ను కలిగి ఉండి, ఒక ఇటరేటర్ను అందించగల ఏదైనా వస్తువు (Lists, Tuples, Dictionaries, Sets, Strings). - Iterator (ఇటరేటర్):
__next__()మెథడ్ను కలిగి ఉండి, ప్రతిసారీ తదుపరి ఎలిమెంట్ను అందించే వస్తువు. - లూప్ ముగింపు: కలెక్షన్లోని డేటా మొత్తం పూర్తయిన వెంటనే ఇటరేటర్
StopIterationఎక్సెప్షన్ను రైజ్ చేస్తుంది. పైథాన్forలూప్ దానిని సైలెంట్గా గుర్తించి ఎటువంటి ఎర్రర్ లేకుండా లూప్ను సురక్షితంగా నిలిపివేస్తుంది.
6 జెనరేటర్లు (Generators) & yield స్టేట్మెంట్ — Lazy Evaluation
జెనరేటర్లు సాధారణ ఫంక్షన్ల లాంటివే, కానీ అవి విలువను return చేసి చనిపోవు; బదులుగా yield స్టేట్మెంట్ ద్వారా విలువను అందించి, తమ ఎగ్జిక్యూషన్ స్టేట్ను (Local Variables, Instruction Pointer) స్తంభింపజేస్తాయి (Pause). మళ్లీ next() పిలిచినప్పుడు సరిగ్గా ఎక్కడైతే ఆగిపోయాయో అక్కడి నుంచే తమ పనిని కొనసాగిస్తాయి:
| ఫీచర్ | సాధారణ లిస్ట్ (Eager Evaluation) | జెనరేటర్ (Lazy Evaluation) |
|---|---|---|
| మెమరీ వినియోగం (1 కోటి సంఖ్యలకు) | ~800 MegaBytes (భారీగా RAM ఆక్రమిస్తుంది) | కేవలం 104 Bytes మాత్రమే! (ఒక్కొక్కటిగా ఉత్పత్తి అవుతుంది) |
| ప్రారంభ వేగం | మొత్తం లిస్ట్ తయారయ్యే వరకు వేచి ఉండాలి (High Latency). | తక్షణమే మొదటి ఫలితం లభిస్తుంది (Zero Startup Latency). |
| డేటా పరిమాణ పరిమితి | సిస్టమ్ RAM సైజుకు పరిమితం (RAM అయిపోతే క్రాష్). | అనంతమైన డేటా స్ట్రీమ్లు (Infinite Streams) ను కూడా నిరంతరం ప్రాసెస్ చేయగలదు. |
సాధారణ ఫంక్షన్ రన్ అయినప్పుడు దాని స్టాక్ ఫ్రేమ్ (Stack Frame) క్రియేట్ అవుతుంది, మరియు
return కాగానే ఆ ఫ్రేమ్ మెమరీ నుండి నాశనమవుతుంది. కానీ ఒక ఫంక్షన్లో yield ఉన్నప్పుడు, పైథాన్ కంపైలర్ దానిని PyGenObject గా గుర్తిస్తుంది.
yield స్టేట్మెంట్ వచ్చినప్పుడు, పైథాన్ ఆ ఫంక్షన్ యొక్క లోకల్ వేరియబుల్స్ మరియు బైట్కోడ్ ఇన్స్ట్రక్షన్ పాయింటర్ (f_lasti) ను హీప్ (Heap) మెమరీలోనే స్తంభింపజేసి భద్రపరుస్తుంది. కాలర్ మళ్లీ next() పిలిచినప్పుడు, ఖచ్చితంగా ఆగిపోయిన f_lasti అడ్రస్ నుండే ఎగ్జిక్యూషన్ పునఃప్రారంభమవుతుంది! ఈ ఆర్కిటెక్చరే ఆధునిక అసెంక్రోనస్ ప్రోగ్రామింగ్ (Async/Await) కు మూలస్తంభం.
7 yield from & బై-డైరెక్షనల్ జెనరేటర్లు (send() Coroutines)
పైథాన్ 3.3 లో ప్రవేశపెట్టబడిన yield from నెస్టెడ్ జెనరేటర్లను మరియు ఇటరబుల్స్ను డీలిగేట్ చేయడానికి అత్యంత సులభతరమైన సింటాక్స్. ఇది లోపలి సబ్-జెనరేటర్ నుండి వచ్చే అన్ని విలువలను నేరుగా కాలర్కు పాస్ చేస్తుంది.
బై-డైరెక్షనల్ కమ్యూనికేషన్: generator.send(value)
జెనరేటర్లు కేవలం బయటకు డేటాను పంపడం (Produce) మాత్రమే కాదు; బయటి కాలర్ నుండి డేటాను లోపలికి స్వీకరించగలవు కూడా! val = yield output అని రాసినప్పుడు, కాలర్ gen.send(new_val) ద్వారా జెనరేటర్లోకి కొత్త డేటాను ఇంజెక్ట్ చేయవచ్చు. ఆధునిక పైథాన్లో asyncio మరియు కోరూటీన్లు (Coroutines) అభివృద్ధి చెందడానికి సరిగ్గా ఈ yield మరియు send() ప్రోటోకాలే మాతృకగా నిలిచింది!
8 పైథాన్ డేటా మోడల్ & మ్యాజిక్ / డండర్ మెథడ్స్ (Python Data Model)
పైథాన్లో క్లాసులు సాధారణ యూజర్-డిఫైన్డ్ టైప్స్ లాగా మాత్రమే కాకుండా, పైథాన్ యొక్క కోర్ సింటాక్స్తో సహజంగా అనుసంధానం కావడానికి Dunder (Double Underscore) మెథడ్స్ తోడ్పడతాయి:
| ఆపరేషన్ / సింటాక్స్ | అంతర్గతంగా పిలవబడే డండర్ మెథడ్ | వివరణ & ఉపయోగం |
|---|---|---|
str(obj) / print(obj) |
__str__(self) |
యూజర్లకు చదవడానికి అనువైన అందమైన టెక్స్ట్ రిప్రజెంటేషన్. |
repr(obj) / Debugger |
__repr__(self) |
డెవలపర్లకు డీబగ్గింగ్ కోసం ఖచ్చితమైన సాంకేతిక సమాచారం. |
len(obj) |
__len__(self) |
కస్టమ్ కంటైనర్ల పొడవును లెక్కించడం. |
obj1 + obj2 |
__add__(self, other) |
కూడిక ఆపరేటర్ ఓవర్లోడింగ్. |
obj1 == obj2 |
__eq__(self, other) |
సమానత్వ పోలిక ఆపరేటర్ ఓవర్లోడింగ్. |
with obj: |
__enter__(self), __exit__(self) |
కాంటెక్స్ట్ మేనేజర్ రిసోర్స్ అలోకేషన్ & సేఫ్ క్లీనప్. |
9 కోడ్ డెమో 1: ఆపరేటర్ ఓవర్లోడింగ్ with Currency & Dunder Suite
పైథాన్ ఆపరేటర్లను (+, *, ==, <) మన యూజర్-డిఫైన్డ్ ఆబ్జెక్టులపై పనిచేసేలా ఓవర్లోడ్ చేసే పూర్తి కోడ్ ఉదాహరణను పరిశీలిద్దాం:
# ఆపరేటర్ ఓవర్లోడింగ్ మరియు పైథాన్ డేటా మోడల్
class Money:
def __init__(self, amount: float, currency: str = "INR"):
self.amount = round(float(amount), 2)
self.currency = currency
# 1. యూజర్ ఫ్రెండ్లీ స్ట్రింగ్
def __str__(self):
symbol = "₹" if self.currency == "INR" else self.currency
return f"{symbol}{self.amount:,.2f}"
# 2. డెవలపర్ డీబగ్గింగ్ రిప్రజెంటేషన్
def __repr__(self):
return f"Money(amount={self.amount}, currency='{self.currency}')"
# 3. కూడిక ఆపరేటర్ (+) ఓవర్లోడింగ్
def __add__(self, other):
if not isinstance(other, Money) or self.currency != other.currency:
raise TypeError("విభిన్న కరెన్సీలను లేదా నాన్-మనీ ఆబ్జెక్టులను కూడలేము!")
return Money(self.amount + other.amount, self.currency)
# 4. గుణకారం ఆపరేటర్ (*) ఓవర్లోడింగ్ (స్కేలార్ నంబర్తో)
def __mul__(self, factor: float):
return Money(self.amount * factor, self.currency)
# 5. సమానత్వ ఆపరేటర్ (==)
def __eq__(self, other):
return isinstance(other, Money) and self.amount == other.amount and self.currency == other.currency
# 6. తక్కువ/ఎక్కువ ఆపరేటర్ (<) సార్టింగ్ కోసం
def __lt__(self, other):
if not isinstance(other, Money) or self.currency != other.currency:
raise TypeError("పోలిక ఒకే కరెన్సీ మధ్య మాత్రమే సాధ్యం!")
return self.amount < other.amount
# టెస్టింగ్
m1 = Money(1500, "INR")
m2 = Money(3250.50, "INR")
m3 = m1 + m2
print("m1:", m1) # __str__ -> ₹1,500.00
print("repr(m1):", repr(m1)) # __repr__ -> Money(amount=1500.0, currency='INR')
print("మొత్తం (m1 + m2):", m3) # ₹4,750.50
print("GST తో (m1 * 1.18):", m1 * 1.18)
print("సార్టింగ్ ఫలితం:", sorted([m2, m1]))
10 కాంటెక్స్ట్ మేనేజర్స్ (Context Managers): __enter__ & contextlib
రిసోర్స్ మేనేజ్మెంట్ కోసం (ఫైళ్లు మూసివేయడం, నెట్వర్క్ సాకెట్ క్లోజ్ చేయడం, డేటాబేస్ లావాదేవీలను కమిట్/రోల్బ్యాక్ చేయడం) with స్టేట్మెంట్ను ఉపయోగిస్తాము:
__enter__(self): రిసోర్స్ను అలోకేట్ చేస్తుంది లేదా లాక్ చేస్తుంది.withబ్లాక్ లోకి ఎంటర్ అవ్వగానే ఇది రన్ అవుతుంది.__exit__(self, exc_type, exc_val, exc_tb): బ్లాక్ ముగియగానే (ఎర్రర్ వచ్చినా రాకపోయినా) రిసోర్స్ను సేఫ్గా క్లోజ్ చేస్తుంది. ఇదిFalseరిటర్న్ చేస్తే ఎక్సెప్షన్ బయటి ప్రోగ్రామ్కు పాస్ అవుతుంది;Trueరిటర్న్ చేస్తే ఎక్సెప్షన్ అణచివేయబడుతుంది.@contextlib.contextmanager: పూర్తి క్లాస్ రాయాల్సిన పని లేకుండా ఒక సాధారణ జెనరేటర్ ఫంక్షన్లోyieldముందు సెటప్ కోడ్,finallyలో క్లీనప్ కోడ్ రాయడం ద్వారా లైట్వెయిట్ కాంటెక్స్ట్ మేనేజర్లను క్షణాల్లో తయారు చేయవచ్చు!- నెస్టెడ్ కాంటెక్స్ట్ మేనేజర్స్ (Multiple Context Managers in a Single with): ఒకే సమయంలో బహుళ రిసోర్స్లను (ఉదాహరణకు సోర్స్ ఫైల్ చదవడం మరియు డెస్టినేషన్ ఫైల్ రాయడం) సురక్షితంగా నిర్వహించడానికి కామాతో
with open('source.log') as src, open('backup.log', 'w') as dst:అని రాయవచ్చు. పైథాన్ రెండింటికీ__enter__మరియు__exit__లను వరుసగా సేఫ్గా ఎగ్జిక్యూట్ చేస్తుంది.
11 కోడ్ డెమో 2: ప్రొడక్షన్ లెవల్ డెకరేటర్లు (@retry & @audit)
నెట్వర్క్ కాల్స్ విఫలమైనప్పుడు ఆటోమేటిక్గా 3 సార్లు రీట్రై చేసే మరియు ఆడిట్ లాగ్ చేసే ప్రొడక్షన్-గ్రేడ్ డెకరేటర్ను చూద్దాం:
import functools
import time
def retry_operation(max_attempts=3, delay_sec=1.0):
"""విఫలమైన ఫంక్షన్లను ఆటోమేటిక్గా రీట్రై చేసే డెకరేటర్."""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
attempts = 0
while attempts < max_attempts:
try:
attempts += 1
return func(*args, **kwargs)
except Exception as err:
print(f"⚠️ [ప్రయత్నం {attempts}/{max_attempts}] విఫలమైంది: {err}")
if attempts >= max_attempts:
print("❌ గరిష్ట రీట్రై పరిమితి ముగిసింది! ఎర్రర్ విసురుతున్నాము.")
raise
time.sleep(delay_sec)
return wrapper
return decorator
# సిమ్యులేషన్: 2 సార్లు ఫెయిల్ అయి 3వ సారి సక్సెస్ అయ్యే API కాల్
call_count = 0
@retry_operation(max_attempts=3, delay_sec=0.5)
def fetch_payment_status(txn_id: str):
global call_count
call_count += 1
if call_count < 3:
raise ConnectionResetError("గేట్వే సర్వర్ స్పందించడం లేదు (504 Gateway Timeout)")
return f"SUCCESS: లావాదేవీ {txn_id} విజయవంతంగా పూర్తయింది!"
print("📡 పేమెంట్ సర్వీస్ కాల్ మొదలైంది...")
result = fetch_payment_status("TXN-90218")
print("🎉 రిజల్ట్:", result)
12 కామన్ బిగినర్స్ మిస్టేక్స్ & ప్రొడక్షన్ బెస్ట్ ప్రాక్టీసెస్
- wraps లేకుండా డెకరేటర్లు రాయడం:
@functools.wraps(func)మర్చిపోతే, ఫ్రేమ్వర్కులు (Flask, FastAPI, Sphinx డాక్యుమెంటేషన్) మీ ఫంక్షన్ను సరైన పేరుతో గుర్తించలేక విచిత్రమైన బగ్స్ను సృష్టిస్తాయి. - Generator Exhaustion Trap: జెనరేటర్ను ఒకసారి లూప్ చేసిన తర్వాత అది ఖాళీ అయిపోతుంది (Exhausted). మళ్లీ అదే జెనరేటర్ను లూప్ చేస్తే ఎటువంటి డేటా రాదు! మళ్లీ డేటా కావాలంటే జెనరేటర్ ఫంక్షన్ను కొత్తగా పిలవాలి లేదా లిస్ట్గా మార్చుకోవాలి.
- డండర్ మెథడ్లలో హెవీ కాంప్యుటేషన్స్ చేయడం:
__len__లేదా__repr__లో నెట్వర్క్ కాల్స్ లేదా భారీ డేటాబేస్ క్వెరీలు చేయకూడదు. అవి తక్షణమే వేగంగా రన్ అయ్యేలా ఉండాలి.
13 రియల్-వరల్డ్ ప్రాజెక్ట్: "Gigabyte-Scale Streaming Server Log Audit Pipeline"
ఈ అధ్యాయంలో నేర్చుకున్న అన్ని అంశాలను (జెనరేటర్లు, yield from, కస్టమ్ డెకరేటర్లు, డండర్ మెథడ్స్తో కూడిన డేటా మోడల్, కాంటెక్స్ట్ మేనేజర్) సమగ్రంగా ఏకీకృతం చేస్తూ — భారీ గిగాబైట్ల సర్వర్ లాగ్ ఫైల్స్ను కేవలం కొన్ని కిలోబైట్ల మెమరీతోనే లైవ్ స్ట్రీమింగ్ చేస్తూ సెక్యూరిటీ బెదిరింపులను గుర్తించే పూర్తి స్థాయి Gigabyte-Scale Streaming Log Audit Pipeline ను నిర్మిద్దాం!
# =====================================================================
# చాప్టర్ 24 ప్రాజెక్ట్: Gigabyte-Scale Streaming Server Log Audit Pipeline
# కాన్సెప్ట్స్: Custom Context Manager, Generators, yield from,
# Dunder Methods (__iter__, __len__, __repr__), @timer Decorator
# =====================================================================
import time
import functools
# 1. పెర్ఫార్మెన్స్ బెంచ్మార్క్ డెకరేటర్
def benchmark_pipeline(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
t0 = time.perf_counter()
res = func(*args, **kwargs)
t1 = time.perf_counter()
print(f"
⚡ పైప్లైన్ ఆడిట్ పూర్తయిన సమయం: {(t1 - t0)*1000:.3f} ms")
return res
return wrapper
# 2. లాగ్ రికార్డ్ క్లాస్ (Python Data Model with Dunder Methods)
class LogRecord:
def __init__(self, ip: str, method: str, path: str, status_code: int, response_ms: float):
self.ip = ip
self.method = method
self.path = path
self.status_code = status_code
self.response_ms = response_ms
def __repr__(self):
return f"LogRecord({self.ip} | {self.method} {self.path} -> {self.status_code})"
def is_security_threat(self) -> bool:
# 401/403/500 ఎర్రర్లు లేదా అనుమానాస్పద పాత్లను గుర్తించడం
suspicious_paths = ["/admin", "/wp-login.php", "/.env", "/config.json"]
return self.status_code in (401, 403, 500) or any(sp in self.path for sp in suspicious_paths)
# 3. కాంటెక్స్ట్ మేనేజర్: సేఫ్ లాగ్ స్ట్రీమ్ సెషన్
class LogStreamAuditSession:
def __init__(self, session_name: str):
self.session_name = session_name
def __enter__(self):
print(f"🔒 [AUDIT SESSION: {self.session_name}] సెషన్ ప్రారంభమైంది. లాగ్ స్ట్రీమ్ లాక్ చేయబడింది.")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type:
print(f"🚨 [AUDIT ALERT] సెషన్లో ఊహించని ఎర్రర్: {exc_val}")
print(f"🔓 [AUDIT SESSION: {self.session_name}] సెషన్ సురక్షితంగా క్లోజ్ అయింది.
")
return False
# 4. జెనరేటర్: భారీ లాగ్ ఫైల్ సిమ్యులేషన్ (మెమరీలో కేవలం 1 లైన్ మాత్రమే ఉంటుంది)
def generate_raw_server_logs():
raw_sample_data = [
"192.168.1.10 GET /api/v1/products 200 45.2",
"10.0.0.5 POST /api/v1/checkout 200 320.1",
"45.33.32.156 GET /admin 403 12.0",
"185.220.101.5 GET /wp-login.php 404 8.5",
"192.168.1.12 GET /api/v1/user/profile 200 65.4",
"45.33.32.156 POST /api/v1/login 401 25.0",
"10.0.0.8 GET /config.json 500 110.0",
"192.168.1.15 GET /index.html 200 18.2"
]
for line in raw_sample_data:
yield line
# 5. జెనరేటర్ పైప్లైన్: రా స్ట్రింగ్ను LogRecord ఆబ్జెక్ట్గా మార్చడం (Lazy Parsing)
def parse_log_stream(raw_stream):
for line in raw_stream:
parts = line.strip().split()
if len(parts) == 5:
ip, method, path, status_code, resp_ms = parts
yield LogRecord(ip, method, path, int(status_code), float(resp_ms))
# 6. జెనరేటర్ ఫిల్టర్: కేవలం సెక్యూరిటీ బెదిరింపులను మాత్రమే ఫిల్టర్ చేయడం
def filter_security_threats(record_stream):
for record in record_stream:
if record.is_security_threat():
yield record
# 7. మొత్తం పైప్లైన్ ఎగ్జిక్యూషన్
@benchmark_pipeline
def run_security_audit():
with LogStreamAuditSession("SOC_HYDERABAD_GATEWAY"):
raw_stream = generate_raw_server_logs()
parsed_stream = parse_log_stream(raw_stream)
threat_stream = filter_security_threats(parsed_stream)
print("🔍 గుర్తించబడిన భద్రతా బెదిరింపులు (Security Threat Events):")
threat_count = 0
for threat in threat_stream:
threat_count += 1
print(f" [హెచ్చరిక #{threat_count}] {threat}")
print(f"
📊 మొత్తం విశ్లేషించబడిన బెదిరింపుల సంఖ్య: {threat_count}")
# పైప్లైన్ రన్ చేద్దాం
run_security_audit()
? మీ అవగాహనను పరీక్షించుకోండి (5 Interactive Quizzes)
1. ఫంక్షన్ డెకరేటర్లలో @functools.wraps(func) ఎందుకు తప్పనిసరిగా వాడాలి?
@functools.wraps వాడకపోతే అసలు ఫంక్షన్ యొక్క పేరు (__name__) మరియు డాక్యుమెంటేషన్ (__doc__) కోల్పోతాము. wraps ఆ మెటాడేటాను సురక్షితంగా కాపాడుతుంది.
2. return మరియు yield స్టేట్మెంట్ల మధ్య ముఖ్యమైన తేడా ఏమిటి?
return ఫంక్షన్ నుండి విలువను ఇచ్చి ఆ ఫంక్షన్ను పూర్తిగా ముగించివేస్తుంది (Terminate). కానీ yield విలువను అందించి, ఫంక్షన్ యొక్క స్థితిని (State & Local variables) స్తంభింపజేస్తుంది (Pause). తర్వాత next() పిలిచినప్పుడు అక్కడి నుండే కొనసాగుతుంది.
3. భారీ డేటాసెట్ల కోసం లిస్టుల కంటే జెనరేటర్లు ఎందుకు సమర్థవంతమైనవి?
4. __str__ మరియు __repr__ మధ్య తేడా ఏమిటి?
__str__ సాధారణ వినియోగదారులకు చదవడానికి సులభంగా ఉండే ఫార్మాట్లో టెక్స్ట్ను అందిస్తుంది (User-friendly). __repr__ డెవలపర్లకు డీబగ్గింగ్ కోసం ఆబ్జెక్ట్ యొక్క ఖచ్చితమైన సాంకేతిక రూపాన్ని అందిస్తుంది (Unambiguous / Developer-focused).
5. కాంటెక్స్ట్ మేనేజర్లో __exit__ మెథడ్ False ను ఎందుకు రిటర్న్ చేస్తుంది?
__exit__ లో False (లేదా None) రిటర్న్ చేస్తే, with బ్లాక్లో వచ్చిన ఏదైనా ఎక్సెప్షన్ అణచివేయబడకుండా (Not suppressed), బయటి ప్రోగ్రామ్కు ప్రయాణించి హ్యాండిల్ చేయబడుతుంది. ఒకవేళ True రిటర్న్ చేస్తే ఎక్సెప్షన్ పూర్తిగా అణచివేయబడుతుంది.
ఈ Streaming Log Audit Engine ని లైవ్గా మన కంపైలర్లో రన్ చేయండి!
ఎటువంటి లోకల్ సెటప్ లేకుండా, బ్రౌజర్లోనే Modern Python 3 కంపైలర్లో ఈ డెకరేటర్లు మరియు జెనరేటర్ల కోడ్ను ఎగ్జిక్యూట్ చేసి అవుట్పుట్ తనిఖీ చేయండి.