Context managers (with)
Overview
The `with` statement is used to wrap the execution of a block of code within a 'context manager'. It guarantees that initialization happens before the block runs, and cleanup (like closing a file or releasing a lock) happens automatically when the block finishes, even if an exception is raised. Mental model: The `with` statement is an automated bouncer; it ensures you do the setup when you enter the club, and perfectly executes the teardown when you leave, no matter how you exit.
Manual resource management using `try...finally` is verbose and error-prone. The `with` statement prevents resource leaks (e.g., leaving files or database connections open).
Where used: Opening files (`open()`), Managing database transactions, Acquiring and releasing thread/asyncio locks
Why learn this
- Your applications will not crash due to 'Too many open files' errors.
- You won't leave database transactions hanging if your code throws an error.
Code walkthrough
with open('test.txt', 'w') as f:
f.write('Data')
print(f.closed)
Focus: print(f.closed) outputs True because exiting the indentation level automatically closes the file.
Aha moment
try:
with open('test.txt', 'w') as f:
raise RuntimeError('Crash!')
except RuntimeError:
pass
print(f.closed)
Prediction: Will the file be closed (True) or left open (False) because of the crash?
Common guess: False, because the program crashed before it could reach the end of the block.
It prints True. The context manager intercepts the exception, immediately closes the file, and then lets the exception continue bubbling up. The cleanup is guaranteed.
Common mistakes
- Using the resource outside the block: If you try to read from a file object after the `with` block has finished, Python will raise an error because the file has already been closed.
- Forgetting the 'as' keyword: To interact with the resource (like the file object), you must use `with open(...) as file:`. Forgetting `as` means you have no variable referencing the opened resource.
Glossary
- context manager
- An object that defines what needs to be set up before a block of code runs and what needs to be cleaned up after. Example: `open('file.txt')`.
- resource leaks
- When a program fails to release system resources like files or memory, eventually causing the system to slow down or crash. Example: forgetting `file.close()`.
Recall questions
- What is the primary guarantee provided by the `with` statement?
- What happens if an exception is raised inside a `with` block?
- Name three common use cases for the `with` statement.
Understanding checks
What is printed when this code is executed?
ValueError
Once the `with` block exits, the file `f` is automatically closed. Attempting to write to a closed file raises a `ValueError: I/O operation on closed file`.
If a division by zero error occurs in the middle of a `with open(...) as f:` block, does the file remain open?
No, it is closed.
The `with` statement guarantees that the teardown (closing the file) executes even if the block is exited via an unhandled exception.
Practice tasks
Convert to Context Manager
Given this manual file writing code, modify it to use a `with` statement so that the file is safely closed automatically.
Challenge
Safely Reading Data
Write code to open an existing file named `data.txt` in read mode using a `with` statement, read its contents into a variable named `content`, and then let the block exit.