Master Context Managers (Beyond with open()
)
You've used with open()
a million times. But did you know you can create your own context managers? They're perfect for resource management (files, locks, connections).
The Classic Way (Using a Class):
class ManagedFile:
def __init__(self, filename):
self.filename = filename
def __enter__(self):
self.file = open(self.filename, 'w')
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
# Usage
with ManagedFile('hello.txt') as f:
f.write('Hello, context manager! ๐')
The Elegant Way (Using contextlib
):
For simpler cases, use @contextmanager
to turn a generator into a context manager.
from contextlib import contextmanager
@contextmanager
def managed_file(filename):
try:
f = open(filename, 'w')
yield f # This is where the 'with' block runs
finally:
f.close() # This ensures cleanup
# Usage is identical!
with managed_file('hello2.txt') as f:
f.write('Even cleaner! ๐งผ')
Why? This ensures resources are always cleaned up, even if an error occurs. It's the Pythonic way to handle setup/teardown.