文件、锁、连接这类资源,用之前要拿到,用完要还。忘了关,或者中途抛异常跳过关闭,都会留尾巴。with 把「进入」和「退出」收成一对。
不用 with:
python
file = open("test.py")
try:
data = file.read()
finally:
file.close()用 with:
python
with open("test.py") as file:
data = file.read()文件关闭、异常路径,都由上下文管理器处理。
它怎么工作
跟在 with 后面的对象要有 __enter__ 和 __exit__:
- 求值得到上下文管理器
- 调
__enter__,返回值赋给as后面的变量 - 跑代码块
- 无论是否异常,调
__exit__
python
class Simple:
def __enter__(self):
print("enter")
return "ok"
def __exit__(self, exc_type, exc_value, traceback):
print("exit")
with Simple() as value:
print("value:", value)输出顺序是 enter → value: ok → exit。
异常
__exit__ 的三个参数是异常类型、异常值、traceback。没有异常时三个都是 None。
python
class Simple:
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
if exc_type is None:
print("没有异常")
else:
print(exc_value)
return True
def boom(self):
return 1 / 0
with Simple() as s:
s.boom()__exit__ 返回 True,异常被吞掉,外面看不到。返回 False 或 None,异常继续往外抛。开发库时,关文件、还锁、断连接,都适合放在 __exit__ 里。