python的with语句浅析
2014-09-11 15:54
232 查看
with 语句适用于对资源进行访问的场合,确保不管在使用过程中是否发生了异常,都会进行必要的清理操作,释放资源。例如,文件使用后自动关闭、线程锁的获取和释放等。
上下文管理协议:包含方法__enter__()和__exit__(),该协议的对象要实现这个两个方法。
上下文管理器:支持上下文管理协议的对象,这种对象实现了__enter__()和__exit__()方法。上下文管理器定义了with语句执行前和执行后的操作。通常使用with语句调用上下文管理器,也可以通过直接调用其方法来使用。
with_body
context_expression:叫作with上下文表达式,该表达式要返回一个上下文管理器。
as字句:可选的。如果制定了as子句,会将上下文管理器的__enter__()方法的返回值赋给target(s)。target(s)可以是单个变量,或者由“()”括起来的元组。
with_body:叫作with语句体。语句体中不管是否发生异常,语句体结束后都会对资源进行自动的“清理”工作。在执行语句体之前会调用上下文管理器的__enter__()方法,在执行完语句体后,会执行__exit__()方法。
Python对一些内建的对象进行了改进,加入了对上下文管理器的支持,可以用于with语句中,比如可以自动关闭文件、线程锁的自动获取和释放等。例如,要对一个文件进行操作,使用with语句可以有如下代码:
比较起来,使用 with 语句可以减少编码量。已经加入对上下文管理协议支持的还有模块 threading、decimal 等。
1.执行congtext_expression,生成上下文管理器context_manager
2.调用上下文管理器的__enter__()方法;如果使用了as字句,则将__enter__()的返回值赋值给as字句中额target(s)
3.执行with-body语句体。
4.不管with-body语句体执行过程中是否发生异常,都执行上下文管理器的__exit__方法,__exit__方法负责执行一些清理工作,比如释放资源等。如果执行过程中没有发生异常,或者语句体中执行了语句break、continue、return,则以None作为参数调用__exit__(None,None,None);如果执行过程中出现异常,则使用sys.exc_info得到的异常信息作为参数调用__exit__(exc_type,exc_value,exc_traceback)
5.出现异常时,如果__exit__(type,value,traceback)方法返回False,则会重新抛出异常,让with之外的语句逻辑来处理异常,这也是通用的做法;如果返回True,则忽略异常,不再对异常进行处理。
与with有关的术语
要使用with语句,首先要明白上下文管理器这一概念。有了上下文管理器,with语句才能工作。下面是有关with语句的一下术语:上下文管理协议:包含方法__enter__()和__exit__(),该协议的对象要实现这个两个方法。
上下文管理器:支持上下文管理协议的对象,这种对象实现了__enter__()和__exit__()方法。上下文管理器定义了with语句执行前和执行后的操作。通常使用with语句调用上下文管理器,也可以通过直接调用其方法来使用。
with的语法格式
with context_expression [as target(s)]:with_body
context_expression:叫作with上下文表达式,该表达式要返回一个上下文管理器。
as字句:可选的。如果制定了as子句,会将上下文管理器的__enter__()方法的返回值赋给target(s)。target(s)可以是单个变量,或者由“()”括起来的元组。
with_body:叫作with语句体。语句体中不管是否发生异常,语句体结束后都会对资源进行自动的“清理”工作。在执行语句体之前会调用上下文管理器的__enter__()方法,在执行完语句体后,会执行__exit__()方法。
Python对一些内建的对象进行了改进,加入了对上下文管理器的支持,可以用于with语句中,比如可以自动关闭文件、线程锁的自动获取和释放等。例如,要对一个文件进行操作,使用with语句可以有如下代码:
清单1:with语句操作文件
<pre class="python" name="code">def read_file_with(fpath): BLOCK_SIZE = 1024 with open(fpath, 'r') as f: while True: block = f.read(BLOCK_SIZE) if block: yield block else: return for line in read_file_with(r"C:\Users\liu.chunming\Desktop\test.txt"): print line
这里使用了with语句,不管在处理文件的过程中是否发生异常,都能保证with语句结束后关闭打开的文件句柄。 (该代码中还使用了yield来迭代读取文件内容。利用固定长度的缓冲区来不断读取文件内容。如果直接对文件对象调用 read() 方法,会导致不可预测的内存占用。) 如果使用传统的try/finally方式,则要写类似的代码如下:
清单2:try/finally语句操作文件
def read_file_tryfinally(fpath): f=open(fpath,'r') BLOCKSIZE=1024 try: while True: block=f.read(BLOCKSIZE) if block: yield block else: break finally: f.close() for line in read_file_tryfinally(r"C:\Users\liu.chunming\Desktop\test.txt"): print line
比较起来,使用 with 语句可以减少编码量。已经加入对上下文管理协议支持的还有模块 threading、decimal 等。
清单3. with 语句执行过程
context_manager = context_expression exit = type(context_manager).__exit__ value = type(context_manager).__enter__(context_manager) exc = True # True 表示正常执行,即便有异常也忽略;False 表示重新抛出异常,需要对异常进行处理 try: try: target = value # 如果使用了 as 子句 with-body # 执行 with-body except: # 执行过程中有异常发生 exc = False # 如果 __exit__ 返回 True,则异常被忽略;如果返回 False,则重新抛出异常 # 由外层代码对异常进行处理 if not exit(context_manager, *sys.exc_info()): raise finally: # 正常退出,或者通过 statement-body 中的 break/continue/return 语句退出 # 或者忽略异常退出 if exc: exit(context_manager, None, None, None) # 缺省返回 None,None 在布尔上下文中看做是 False
1.执行congtext_expression,生成上下文管理器context_manager
2.调用上下文管理器的__enter__()方法;如果使用了as字句,则将__enter__()的返回值赋值给as字句中额target(s)
3.执行with-body语句体。
4.不管with-body语句体执行过程中是否发生异常,都执行上下文管理器的__exit__方法,__exit__方法负责执行一些清理工作,比如释放资源等。如果执行过程中没有发生异常,或者语句体中执行了语句break、continue、return,则以None作为参数调用__exit__(None,None,None);如果执行过程中出现异常,则使用sys.exc_info得到的异常信息作为参数调用__exit__(exc_type,exc_value,exc_traceback)
5.出现异常时,如果__exit__(type,value,traceback)方法返回False,则会重新抛出异常,让with之外的语句逻辑来处理异常,这也是通用的做法;如果返回True,则忽略异常,不再对异常进行处理。
相关文章推荐
- 深入浅析python with语句简介
- python with 语句研究
- python with语句的用法
- 浅谈 Python 的 with 语句
- 浅谈 Python 的 with 语句
- 理解Python的With语句
- 非正常研究-----python with 语句研究
- 理解Python的With语句
- Python开发——理解With语句
- 理解Python的With语句
- Python With语句
- 【原创翻译】理解python的with语句
- Python With语句
- 理解Python的With语句
- 理解Python的with语句
- python的with语句
- python 中的反射,装饰器,with语句
- Python的with语句
- Python 的 with 语句详解
- 浅谈 Python 的 with 语句