一、读取文件数据
# example01.py
file = open("/tmp/foo.txt")
data = file.read()
file.cloae()
# example02.py
file = open("/tmp/foo.txt")
try:
data = file.read()
finally:
file.cloae()
# example03.py
with open("/tmp/foo.txt") as file:
data = file.read()
二、with的运行机制
with statement:用上下文管理器(with statement context managers)定义的方法来封装块的执行.
with上下文管理器:
object.__enter__(self) // 返回的值作为as的值
object.__exit__(self, exc_type, exc_value, traceback) // 这些参数描述了context的异常退出。如果没有异常,三个参数都为None.
处理流程:
(1) 上下文表达式求值以获得一个上下文管理器(context manager)
(2) 加载context manager的__exit__(),以便后边使用
(3) 调用context manager的__enter__()
(4) 如果with表达式存在一个目标,把__enter__()的返回值给目标
(5) 执行内容
(6) 调用context manager的__exit__(),如果异常发生,与之相关联的参数exc_type, exc_value, traceback传给__exit__()方法。否则,参数赋值为None.
如果代码块由于异常退出,__exit__()返回false,异常发生;如果__exit__()返回的是true,异常就不存在,继续执行with的表达式。
在with后面的代码块抛出任何异常时,__exit__()方法被执行。开发库时,清理资源,关闭文件等操作都可以放在__exit__()方法中。
# with_example01.py
class Sample:
''' Sample'''
def __enter__(self):
print("In __enter__()")
return "Foo"
def __exit__(self, type, value, trace):
print("In __exit__()")
def get_sample():
return Sample()
with get_sample() as sample:
print("sample:", sample)
with_example01.py 演示了正常的处理流程,结果如下
# with_example02.py
class Sample:
''' Sample'''
def __enter__(self):
return self # return a new Sample object
def __exit__(self, type, value, trace):
print("type:", type)
print("value:", value)
print("trace:", trace)
def do_something(self):
bar = 1/0
return bar + 10
with Sample() as sample:
sample.do_something()
with_example02.py 演示了异常情况,运行结果如下: