🔒 Context Managers

Resource Management with 'with'

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