Interview question
How does the contextlib module simplify writing context managers? contextlib module context managers लिखना कैसे आसान बनाता है?
Answer
The contextlib.contextmanager decorator lets you write a context manager using a generator function instead of a full class with __enter__/__exit__, using yield to separate setup from teardown.
from contextlib import contextmanager
@contextmanager
def managed_file(filename, mode):
print('Setup: opening file')
f = open(filename, mode)
try:
yield f # everything before yield = __enter__, after = __exit__
finally:
print('Teardown: closing file')
f.close() # runs even if an exception occurs in the with block
with managed_file('data.txt', 'w') as f:
f.write('Hello')
# Setup: opening file
# Teardown: closing file
# Comparing class-based vs generator-based approaches
# Class-based (more code, more control)
class Timer:
def __enter__(self):
import time
self.start = time.time()
return self
def __exit__(self, *args):
print(f'{time.time() - self.start:.4f}s')
# Generator-based equivalent (less code, same result)
import time
@contextmanager
def timer():
start = time.time()
yield
print(f'{time.time() - start:.4f}s')
with timer():
sum(range(1000000))
# contextlib.suppress - shorthand for ignoring specific exceptions
from contextlib import suppress
with suppress(FileNotFoundError):
open('might_not_exist.txt') # no error even if file doesn't exist
# Equivalent to:
try:
open('might_not_exist.txt')
except FileNotFoundError:
passcontextlib.contextmanager decorator generator function से context manager लिखने देता है, पूरी class की बजाय, yield से setup को teardown से अलग करता है।
from contextlib import contextmanager
@contextmanager
def managed_file(filename, mode):
print('Setup: file खोलना')
f = open(filename, mode)
try:
yield f # yield से पहले = __enter__, बाद = __exit__
finally:
print('Teardown: file बंद करना')
f.close()
with managed_file('data.txt', 'w') as f:
f.write('Hello')
# Generator-based timer
import time
@contextmanager
def timer():
start = time.time()
yield
print(f'{time.time() - start:.4f}s')
with timer():
sum(range(1000000))
# contextlib.suppress - specific exceptions ignore करने का shorthand
from contextlib import suppress
with suppress(FileNotFoundError):
open('might_not_exist.txt')
# बराबर है:
try:
open('might_not_exist.txt')
except FileNotFoundError:
passWas this answer clear?