最推荐的方式是使用 with 语句;try-except-finally 虽可行但需手动检查 f 是否存在且未关闭,以防 AttributeError 或冗余操作,而 with 可自动安全处理所有异常和清理场景。

在Python中,用 try-except-finally 确保文件句柄在异常时关闭是可行的,但**不是最推荐的方式**;更安全、更简洁的做法是使用 with 语句(上下文管理器)。不过,理解 try-except-finally 的写法有助于掌握资源管理逻辑。
手动用 try-except-finally 关闭文件
核心思路是:把 open() 放在 try 前或 try 中,确保 file 变量被定义;无论是否出错,都在 finally 块中调用 .close()。注意要判断文件对象是否存在且未关闭,避免重复关闭或操作 None。
示例:
f = None
try:
f = open("data.txt", "r")
data = f.read()
# 可能抛出异常的操作,如解析错误
int(data.strip()) # 假设内容不是数字
except ValueError as e:
print("数据格式错误:", e)
finally:
if f and not f.closed:
f.close()
print("文件已关闭")
为什么 finally 中要检查 f 和 closed?
如果不加判断,可能出现以下问题:
立即学习“Python免费学习笔记(深入)”;
-
f 未成功创建(比如路径不存在导致
FileNotFoundError在open()时就抛出),此时f仍是None,直接调用f.close()会触发AttributeError; -
文件已在 except 中主动关闭,再次调用
close()虽然安全,但不必要;检查f.closed可避免冗余操作。
对比 with 语句:更可靠的选择
with 语句本质就是基于上下文管理协议自动调用 __enter__ 和 __exit__,即使发生异常,__exit__ 也保证执行(等价于隐式的 finally + 安全关闭)。
等效且更简洁的写法:
try:
with open("data.txt", "r") as f:
data = f.read()
int(data.strip())
except ValueError as e:
print("数据格式错误:", e)
# 文件在此处已自动关闭,无需手动处理
✅ 自动处理打开失败(open 抛异常时,__enter__ 未完成,不会执行 __exit__);
✅ 正常/异常/提前 return 都能确保关闭;
✅ 代码更短,意图更清晰。
进阶:自定义类支持 with(了解原理)
如果你需要管理非文件资源,可参考文件对象的设计:实现 __enter__ 返回资源本身,__exit__ 负责清理。例如:
class SafeFile:
def __init__(self, name, mode):
self.name = name
self.mode = mode
self.file = None
def __enter__(self):
self.file = open(self.name, self.mode)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
# 使用方式相同
with SafeFile("data.txt", "r") as f:
print(f.read())


















