Context Managers
Context managers handle resource allocation and cleanup automatically. The 'with' statement ensures resources are properly released even if errors occur.
💻 Using 'with' Statement
# Without context manager (manual cleanup)
file = open('data.txt', 'r')
try:
data = file.read()
finally:
file.close()
# With context manager (automatic cleanup)
with open('data.txt', 'r') as file:
data = file.read()
# File automatically closed after block
# Multiple context managers
with open('input.txt', 'r') as infile, open('output.txt', 'w') as outfile:
for line in infile:
outfile.write(line.upper())🔧 Creating Context Managers
# Using __enter__ and __exit__
class FileManager:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
self.file = None
def __enter__(self):
self.file = open(self.filename, self.mode)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
with FileManager('data.txt', 'w') as f:
f.write('Hello!')
# Using contextlib
from contextlib import contextmanager
@contextmanager
def timer():
import time
start = time.time()
yield
end = time.time()
print(f"Took {end - start:.2f}s")
with timer():
# Your code here
sum(range(1000000))🎯 Key Takeaways
- with statement: Automatic resource management
- __enter__: Setup method (returns resource)
- __exit__: Cleanup method (always runs)
- @contextmanager: Decorator for simple managers
- Exception safety: Cleanup even on errors
- Common uses: Files, locks, database connections