
Photo by cottonbro studio on Pexels
We’ve all been there: writing a dozen lines of boilerplate code just to open a file, write to it, and pray to the gods of garbage collection that it actually closes before our script crashes. Enter Python’s context managers—the elegant, blood-pressure-lowering feature you should have been using since day one, wrapped neatly in a simple with statement.
Welcome back to the Old Lane 17 workshop, where we prefer our code clean, our terminal workflows swift, and our enterprise bloat locked safely outside. Today, let’s talk about resource management.
The Real-World Gotcha: The Leaky File Descriptor
Picture this: You’re writing a quick script to process logs. You open a file, read some data, and somewhere in the middle of your loop, a wild TypeError appears. Your script craters.
If you wrote old-school procedural code without proper cleanup, your OS might hold onto that file descriptor until the process finally dies. Do that enough times in a production loop, and you’ll run out of file descriptors faster than a startup runs through seed funding.
Here is the sad, repetitive way we used to write this:
python# Please, no one do this in 2024.
f = open("important_logs.txt", "w")
try:
f.write("System nominal... mostly.")
# Imagine a crash right here 💥
raise RuntimeError("Everything is on fire!")
finally:
f.close() # At least we remembered this, right?
Sure, the finally block saves us, but it’s verbose, ugly, and forces us to write defensive cleanup code every single time we touch a resource. There has to be a better way.
Enter the with Statement
Python’s context managers handle the setup and teardown automatically. Whether your code succeeds or bursts into flames, the context manager guarantees that the cleanup code (like closing a file or releasing a database lock) runs.
Here is the clean, modern way to do it:
python# Clean, readable, and safe.
with open("important_logs.txt", "w") as f:
f.write("System nominal... mostly.")
# Even if this raises an error, the file is safely closed.
No finally. No manual .close() calls. Just pure, unadulterated serenity.
Roll Your Own: The @contextmanager Magic
What happens when your resource isn’t a file? What if you need to time a block of code, manage a temporary database transaction, or temporarily change a working directory?
You can write your own context manager using the contextlib module. No need to write a class with __enter__ and __exit__ methods unless you’re feeling extra bureaucratic today.
Here is a practical timer context manager:
pythonimport time
from contextlib import contextmanager
@contextmanager
def timer(task_name):
start_time = time.time()
print(f"[{task_name}] Starting...")
try:
yield # Control yields back to the 'with' block
finally:
elapsed = time.time() - start_time
print(f"[{task_name}] Finished in {elapsed:.4f} seconds.")
# Using our custom context manager
with timer("Database Migration"):
# Pretend we are doing heavy lifting here
time.sleep(1.5)
print("Migrating tables...")
When you run this, it handles the bookkeeping before and after your block executes, completely insulated from whatever exceptions happen in the middle.
Next time you find yourself writing manual cleanup boilerplate, take a step back, look at the with statement, and thank the Python gods for keeping our terminal windows green and our panic levels low.
Published by the Old Lane Developer Desk.
Disclaimer: This article was generated and formatted with the assistance of Artificial Intelligence.


