<摘要>
生产环境里,很多“文件句柄耗尽”或“数据库连接池爆满”的事故,
并不是代码逻辑太复杂,而是异常发生时资源没有正确释放,
平时代码里,这类问题占了相当大的比例。
Python 中处理这类问题最简单有效的方式,就是用 with 语句,
它让资源自动管理,不容易出错。
f = open('data.txt', 'w')f.write('Hello World')# 如果这行代码出错了,下面的 close 永远不会执行!do_something_complex()f.close()
文件没关,句柄一直占用,时间长了系统就会报错。
f = open('data.txt', 'w')try:f.write('Hello World')do_something_complex()finally:# 无论是否报错,这里都会执行f.close()
这样即使出异常,文件也会关闭。安全,但代码多几行,缩进也多,写起来不方便。
withopen('data.txt', 'w') as f:f.write('Hello World')do_something_complex()# 出了缩进块,文件自动关闭。哪怕报错,也自动关闭。
with 块结束时,文件自动关闭。正常结束会关,抛异常也会关。代码短,逻辑清楚。
__enter__:进入 with 块时调用,通常用来获取资源(打开文件、连接数据库等)。
__exit__:离开 with 块时调用(不管正常结束还是异常),通常用来释放资源(关闭文件、断开连接等)。
# 旧时代的写法with open('input.txt') as fin:with open('output.txt', 'w') as fout:fout.write(fin.read())
# Python 3.10+ 新潮写法with (open('input.txt', 'r') as fin,open('output.txt', 'w') as fout):fout.write(fin.read())
代码更平整,好读。建议用新写法。
with open('test.txt') as f:content = "Secret Data"print(content) # 竟然能打印出来!输出:Secret Dataprint(f) # 文件对象也还在!(虽然已经处于 closed 状态)