Context Managers (with Statement)
Context Managers
Section titled “Context Managers”Introduction
Section titled “Introduction”A context manager handles setup and cleanup automatically using the with statement. The most common use is file handling.
Using Context Managers
Section titled “Using Context Managers”# File handlingwith open("file.txt", "r") as f: content = f.read()# File is automatically closed here
# Database connectionswith db_connection() as conn: conn.execute("SELECT * FROM users")# Connection is automatically closed
# Thread lockslock = threading.Lock()with lock: # Critical section shared_counter += 1# Lock is automatically releasedCreating Context Managers
Section titled “Creating Context Managers”Class-based
Section titled “Class-based”class ManagedFile: def __init__(self, filename, mode="r"): self.filename = filename self.mode = mode
def __enter__(self): print(f"Opening {self.filename}") self.file = open(self.filename, self.mode) return self.file
def __exit__(self, exc_type, exc_val, exc_tb): print(f"Closing {self.filename}") self.file.close() # Return False to propagate exceptions # Return True to suppress exceptions return False
with ManagedFile("test.txt", "w") as f: f.write("Hello, World!")Using contextlib
Section titled “Using contextlib”from contextlib import contextmanager
@contextmanagerdef managed_file(filename, mode="r"): print(f"Opening {filename}") file = open(filename, mode) try: yield file # This is the value in `as` finally: print(f"Closing {filename}") file.close()
with managed_file("test.txt", "w") as f: f.write("Hello, World!")The contextlib Module
Section titled “The contextlib Module”from contextlib import contextmanager, suppress, redirect_stdoutimport os
# Suppress specific exceptionswith suppress(FileNotFoundError): os.remove("nonexistent.txt") # No error!
# Redirect stdoutwith open("output.log", "w") as f: with redirect_stdout(f): print("This goes to the log file")
# Nested context managers@contextmanagerdef change_dir(path): old_dir = os.getcwd() os.chdir(path) try: yield finally: os.chdir(old_dir)
with change_dir("/tmp"): print(os.getcwd()) # /tmpprint(os.getcwd()) # Back to originalBest Practices
Section titled “Best Practices”- Always use
withfor resource management — files, locks, connections - Use
@contextmanagerfor simple context managers instead of writing a class - Handle exceptions properly in
__exit__— return False to propagate - Use
contextlib.suppressto ignore expected exceptions cleanly
Practice Exercises
Section titled “Practice Exercises”Exercise 1: Create a Timer context manager that measures and prints execution time.
Exercise 2: Create a context manager that temporarily changes environment variables and restores them on exit.