with Statement (Context Managers)
with statement Python ka "context manager" protocol use karta hai — with open(...) as f: block ke andar file automatically open rehti hai, block khatam hote hi (normally ya exception se) automatically close() ho jaati hai. Ye RAII pattern ka Python equivalent hai.
Apni khud ki classes ko bhi context-manager-compatible bana sakte ho — __enter__ aur __exit__ dunder methods implement karke. __exit__ guaranteed chalta hai, chahe block mein exception aaye.
# Modern, recommended way:
with open("data.txt", "r") as f:
content = f.read()
print(content)
# yahin automatically f.close() ho jaata hai — chahe exception aaye ya na aaye!
# Custom context manager:
class Timer:
def __enter__(self):
import time
self.start = time.time()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
import time
print(f"Time taken: {time.time() - self.start:.4f}s")
with Timer():
total = sum(range(1000000)) # kaam karo
# automatically time print ho jaata hai block khatam hote hi- with open(...) as f: — automatic close(), chahe exception aaye
- __enter__/__exit__ = custom context managers banane ke liye
- Python ka RAII jaisa pattern — resource safety
Poori class (__enter__/__exit__) likhne ke bajaye, @contextmanager decorator se generator function se bhi context manager bana sakte ho — chhote cases ke liye simpler.
from contextlib import contextmanager
import time
@contextmanager
def timer():
start = time.time()
yield # yahi "with" block ka code chalta hai
print(f"Time: {time.time() - start:.4f}s")
with timer():
total = sum(range(1000000))
# automatically time print hota haiEk with statement mein multiple context managers comma se separate karke ek saath use kar sakte ho — jaise ek file se padhna aur doosri mein likhna, dono automatically close honge.
with open("input.txt", "r") as infile, open("output.txt", "w") as outfile:
for line in infile:
outfile.write(line.upper())
# dono files automatically close ho jaati hain block khatam hote hi