Precise exception handling and guaranteed cleanup
Assistance allowed only after prediction and observed evidence are recorded.
Prerequisites
Complete the previous activity; use the listed recovery link if blocked.
Learning Objective
Predict which of try, except, else, and finally run when a file open succeeds and when it raises FileNotFoundError, then verify. Replace manual close() with a with block and explain why a bare except is prohibited.
Instructions
try holds the risky call. except FileNotFoundError as e handles exactly one expected failure, and e.filename names the missing path. else runs only when no exception occurred; finally always runs. A bare except: is prohibited because it also swallows KeyboardInterrupt and real programming errors, turning diagnosis into guesswork. For file objects, with is the predefined cleanup action and makes finally unnecessary.
Practice & Prediction Log
Work in an empty temporary folder. Run this script twice: first with notes.txt absent, then again after creating it with printf 'hi\n' > notes.txt.
try:
f = open("notes.txt", encoding="utf-8")
except FileNotFoundError as e:
print("cannot open", e.filename)
else:
print("opened", f.name)
f.close()
finally:
print("cleanup")
Before each run, write down which of try / except / else / finally execute and the exact output. Then (1) rewrite it so a with block closes the file instead of else + f.close(), and show f.closed is True after the block; (2) name two things a bare except: would hide.
Predict each run line by line before executing. Then rewrite the else/close() part as a with block and confirm the file is closed without the finally clause.
Clause trace. notes.txt absent: open() raises FileNotFoundError, so except runs, else is skipped, finally runs:
cannot open notes.txt
cleanup
notes.txt present: try succeeds, except is skipped, else runs (and closes f), finally runs:
opened notes.txt
cleanup
With-based rewrite (save as with_version.py and run it in the same two states):
def show(path):
try:
with open(path, encoding="utf-8") as f:
print("opened", f.name)
except FileNotFoundError as e:
print("cannot open", e.filename)
return
print("closed after with:", f.closed)
show("notes.txt")
notes.txt present:
opened notes.txt
closed after with: True
notes.txt absent:
cannot open notes.txt
The with statement closes the file whenever its block exits, normally or through an exception, so neither the manual close() nor a finally clause is needed for the file. The except stays outside the with because open() itself is what raises.
Two things a bare except: hides: (1) KeyboardInterrupt (Ctrl+C) and SystemExit, because a bare except catches every BaseException; (2) programming errors such as a NameError from a typo. Demonstration:
try:
prnt("hi")
except:
print("something went wrong")
something went wrong
The misspelled print raised NameError, and the bare except reported it as a vague failure. With except FileNotFoundError the same typo would surface as a NameError traceback pointing at the bad line.
You state exactly which clauses run for success and for failure, convert the else/close() pattern into a with block correctly, and name two things a bare except would hide.
Authoritative Source Resources & Provenance
The Python Tutorial: Errors and Exceptions
Relevant Section / Range: Sections 8.3–8.6 (handling exceptions, else, finally, cleanup actions)
Verified Version & Date: Python 3.12 documentation; verified 2026-10-30
Primary reference for try/except/else/finally semantics and the with statement as predefined cleanup.
Every clause behavior in the lesson is demonstrated by runnable local snippets.
Compared Candidate Sources & Selection Analysis (2)
Solid lecture treatment, but paced for a semester course and requires video viewing; the tutorial section matches the exercise scope directly.
Reference-style exception hierarchy listing rather than the tutorial narrative; retained as lookup material for the recovery drills.