精确的异常处理与有保证的清理
仅在记录预测和观察到的证据之后,才允许使用辅助。
Prerequisites
完成上一项活动;如遇阻塞,使用所列恢复链接。
Learning Objective
预测文件打开成功与抛出 FileNotFoundError 时 try、except、else、finally 各执行哪些子句,然后验证。把手动 close() 换成 with 块,并解释为什么禁止裸 except。
Instructions
try 放有风险的调用。except FileNotFoundError as e 只处理这一种预期失败,e.filename 给出缺失路径。else 只在无异常时运行;finally 总是运行。裸 except: 被禁止,因为它连 KeyboardInterrupt 和真正的程序错误也会吞掉,让诊断变成瞎猜。对文件对象来说,with 是预定义的清理动作,有了它 finally 就不再必要。
Practice & Prediction Log
在一个空的临时文件夹中操作。把这个脚本运行两次:第一次 notes.txt 不存在,第二次先用 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")
每次运行前,写下 try / except / else / finally 中哪些会执行以及确切输出。然后 (1) 改写成用 with 块关闭文件,取代 else + f.close(),并展示块结束后 f.closed 为 True;(2) 举出裸 except: 会隐藏的两样东西。
执行前逐行预测两次运行。然后把 else/close() 部分改写成 with 块,确认没有 finally 子句文件也会被关闭。
子句追踪。notes.txt 不存在:open() 抛出 FileNotFoundError,所以 except 执行,else 被跳过,finally 执行:
cannot open notes.txt
cleanup
notes.txt 存在:try 成功,except 被跳过,else 执行(并关闭 f),finally 执行:
opened notes.txt
cleanup
基于 with 的改写(保存为 with_version.py,并在同样两种状态下运行):
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 存在:
opened notes.txt
closed after with: True
notes.txt 不存在:
cannot open notes.txt
with 语句在块退出时(无论正常结束还是因异常)都会关闭文件,所以对这个文件来说,手动 close() 和 finally 子句都不再需要。except 留在 with 外面,因为抛出异常的正是 open() 本身。
裸 except: 会隐藏的两样东西:(1) KeyboardInterrupt(Ctrl+C)和 SystemExit,因为裸 except 会捕获所有 BaseException;(2) 程序错误,比如拼写错误导致的 NameError。演示:
try:
prnt("hi")
except:
print("something went wrong")
something went wrong
拼错的 print 抛出了 NameError,裸 except 却把它报告成一个含糊的失败。若用 except FileNotFoundError,同样的拼写错误会以指向出错行的 NameError traceback 暴露出来。
能准确说出成功与失败各执行哪些子句,正确把 else/close() 改成 with 块,并举出裸 except 会隐藏的两样东西。
Authoritative Source Resources & Provenance
The Python Tutorial: Errors and Exceptions
对应章节 / 时间戳: Sections 8.3–8.6 (handling exceptions, else, finally, cleanup actions)
验证版本与日期: 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.
对比候选资源与选型分析 (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.