Entering a Flaky Context Manager in Python2020-02-07
Here’s a little Python problem I encountered recently.
I want to open and read a file cautiously.
open() raises an
OSError, for whatever reason, I want to do nothing.
Otherwise, I want to print out all the lines in the file.
If I open the file, I want to always
close() it - even if the printing of the lines raises an error.
But if the printing does raise an error, even an
OSError, that should be raised.
What’s the most idiomatic way to do this?
If you have experienced similar problems before, you were likely thinking of using
with open() like so:
try: with open("file.txt") as fp: for line in fp: print(line) except OSError: pass
This works great, apart from for the last point: “if the printing does raise an error, even an
OSError, that should be raised”.
Right now such an
OSError would be caught by the
Following my post on limiting try clauses, we want to limit the
try to only be around
Effectively, we want something like this non-existent, poorly indented syntax:
try: with open("foobar") as fp: except OSError: pass else: for line in fp: print(line)
It would be neat if it works, but it doesn’t. So how can we wrap a
try around just our
open context manager?
Enter the standard library’s
It’s a meta context manager, allowing you to enter zero or more context managers, and it will close them later for you.
To solve our problem, we need to want to use
with ExitStack() combined with
enter_context on our
We then use a standard
try/except/else to catch
OSError on the
open() but nowhere else.
The full solution looks like:
from contextlib import ExitStack with ExitStack() as stack: try: fp = stack.enter_context(open("file.txt", "r")) except OSError: pass else: for line in fp: print(line)
Thanks to Tom Grainger for reminding me to use
I hope this helps you use context managers betterer,
🤩 Django-Related Sales for Black Friday Week 🤩
One summary email a week, no spam, I pinky promise.
- Tuples versus Lists in Python
- Limit Your Try Clauses in Python
- Simplify Your If Statements That Return Booleans
© 2020 All rights reserved.