with语句
With 语句是在Python2.5版本开始引入的,通过
from __future__ import with_statement
导入后才可以使用。在2.6版本以后正式成为缺省的功能。
要使用with语句,必须要明白上下文管理器这一概念。
上下文管理协议:
包含方法
__enter__()
和__exit__()
,支持该协议的对象要实现这两个方法。
上下文管理器:
支持上下文管理协议的对象,这种对象实现了
__enter__()
和__exit__()
方法,上下文管理器定义执行with语句时要建立的运行时上下文,负责执行with语句上下文中的进入和退出操作。通常使用with调用上下文管理器,也可以直接调用其方法来执行。
运行时上下文:
由上下文管理器创建,通过上下文管理器的 enter() 和
__exit__()
方法实现,__enter__()
方法在语句体执行之前进入运行时上下文,__exit__()
在语句体执行完后从运行时上下文退出。with 语句支持运行时上下文这一概念。
上下文表达式:
with 语句中跟在关键字 with 之后的表达式,该表达式要返回一个上下文管理器对象。
语句体:
with 语句包裹起来的代码块,在执行语句体之前会调用上下文管理器的
__enter__()
方法,执行完语句体之后会执行__exit__()
方法。
实现
打开一个文件时:
with open(r"/home/admin/README.txt") as f:
for line in f:
print(line)
threading 锁机制:
import threading
lock = threading.Lock()
with lock:
print("Used with")
未使用锁:
import threading
lock = threading.Lock()
lock.acquire()
try:
logging.debug('Lock acquired directly')
finally:
lock.release()
自定义上下文管理器
class MyContext(object):
def __enter__(self):
print("In context!")
return self
def __exit__(self, type_, value, trace):
print(type_ ,value, trace)
print("Out context!")
def foo(self):
div = 10/0
return div
with MyContext() as my_context:
print(my_context)
my_context.foo()
注意到
__exit__
里面有三个参数,这三个参数是异常发生是自动传递的参数,这个例子中打印如下
>>In context!
<__main__.MyContext object at 0x7f61d0c25450>
(<type 'exceptions.ZeroDivisionError'>, ZeroDivisionError('integer division or modulo by zero',), <traceback object at 0x7f61d0b3a950>)
Out context!
Traceback (most recent call last):
File "a.py", line 16, in <module>
my_context.foo()
File "a.py", line 11, in foo
div = 10/0
ZeroDivisionError: integer division or modulo by zero
可以看出type_表示异常的类型;value表示异常对象;trace是异常跟踪对象