在读写文件时,为了确保文件流关闭,一般会这么写
# 打开文件
f = open('file.txt')
try:
for line in f:
# 读取文件内容 执行其他操作
# do_something...
finally:
# 保证关闭文件
f.close()
但是如果使用with语句就可以
with open('file.txt') as f:
for line in f:
# do_something...
with 的语法格式:
with context_expression [as target(s)]:
with-body
不过,要想使用 with语法块,with后面的的对象需要实现「上下文管理器协议」。
一个类在 Python 中,只要实现以下方法,就实现了「上下文管理器协议」:
__enter__:在进入 with 语法块之前调用,返回值会赋值给 with 的 target__exit__:在退出 with 语法块时调用,一般用作异常处理例子
class TestContext:
def __enter__(self):
print('__enter__')
return 1
# exc_type:异常类型
# exc_value:异常对象
# exc_tb:异常堆栈信息
def __exit__(self, exc_type, exc_value, exc_tb):
print('exc_type: %s' % exc_type)
print('exc_value: %s' % exc_value)
print('exc_tb: %s' % exc_tb)
with TestContext() as t:
print('t: %s' % t)
a = 1 / 0
# Output:
# __enter__
# t: 1
# exc_type: <type 'exceptions.ZeroDivisionError'>
# exc_value: integer division or modulo by zero
# exc_tb: <traceback object at 0x10d66dd88>
# Traceback (most recent call last):
# File "base.py", line 16, in <module>
# a = 1 / 0
# ZeroDivisionError: integer division or modulo by zero
所以File类的伪代码大概是这样的
class File:
def __enter__(self):
return file_obj
def __exit__(self, exc_type, exc_value, exc_tb):
# with 退出时释放文件资源
file_obj.close()
# 如果 with 内有异常发生 抛出异常
if exc_type is not None:
raise exception