Python之with语句原理
2017-07-07 14:52
549 查看
我们看一个with处理文件操作的实例:
这段代码的作用:打开一个文件,如果一切正常,把文件对象赋值给f,然后用迭代器遍历文件中每一行,当完成时,关闭文件;
而无论在这段代码的任何地方,如果发生异常,此时文件仍会被关闭。
with看起来如此简单,但是其背后还有一些工作要做,因为你不能对Python的任意对象使用with语句,它仅能工作于支持上下文管理协议(context management protocol)的对象。
也就是说,只有内建了“上下文管理”的对象可以和with一起工作,目前支持该协议的对象有:
file
decimal.Context
thread.LockType
threading.Lock
threading.RLock
threading.Condition
threading.Semaphore
threading.BoundedSemaphore
当with语句执行时,便执行上下文表达式(context_expr)来获得一个上下文管理器,上下文管理器的职责是提供一个上下文对象,用于在with语句块中处理细节:
一旦获得了上下文对象,就会调用它的__enter__()方法,将完成with语句块执行前的所有准备工作,如果with语句后面跟了as语句,则用__enter__()方法的返回值来赋值;
当with语句块结束时,无论是正常结束,还是由于异常,都会调用上下文对象的__exit__()方法,__exit__()方法有3个参数,如果with语句正常结束,三个参数全部都是 None;如果发生异常,三个参数的值分别等于调用sys.exc_info()函数返回的三个值:类型(异常类)、值(异常实例)和跟踪记录(traceback),相应的跟踪记录对象。
因为上下文管理器主要作用于共享资源,__enter__()和__exit__()方法干的基本是需要分配和释放资源的低层次工作,
比如:数据库连接、锁分配、信号量加/减、状态管理、文件打开/关闭、异常处理等。
知道了上面这些,我们就可以尝试在自定义类里面创建__enter__()和__exit__()方法,来配合with语句创建类实例了:
输出:
另外python库中还有一个模块contextlib,使你不用构造含有__enter__, __exit__的类就可以使用with:
输出:
with open('/etc/passwd') as f: for line in f: print(line)
这段代码的作用:打开一个文件,如果一切正常,把文件对象赋值给f,然后用迭代器遍历文件中每一行,当完成时,关闭文件;
而无论在这段代码的任何地方,如果发生异常,此时文件仍会被关闭。
with看起来如此简单,但是其背后还有一些工作要做,因为你不能对Python的任意对象使用with语句,它仅能工作于支持上下文管理协议(context management protocol)的对象。
也就是说,只有内建了“上下文管理”的对象可以和with一起工作,目前支持该协议的对象有:
file
decimal.Context
thread.LockType
threading.Lock
threading.RLock
threading.Condition
threading.Semaphore
threading.BoundedSemaphore
当with语句执行时,便执行上下文表达式(context_expr)来获得一个上下文管理器,上下文管理器的职责是提供一个上下文对象,用于在with语句块中处理细节:
一旦获得了上下文对象,就会调用它的__enter__()方法,将完成with语句块执行前的所有准备工作,如果with语句后面跟了as语句,则用__enter__()方法的返回值来赋值;
当with语句块结束时,无论是正常结束,还是由于异常,都会调用上下文对象的__exit__()方法,__exit__()方法有3个参数,如果with语句正常结束,三个参数全部都是 None;如果发生异常,三个参数的值分别等于调用sys.exc_info()函数返回的三个值:类型(异常类)、值(异常实例)和跟踪记录(traceback),相应的跟踪记录对象。
因为上下文管理器主要作用于共享资源,__enter__()和__exit__()方法干的基本是需要分配和释放资源的低层次工作,
比如:数据库连接、锁分配、信号量加/减、状态管理、文件打开/关闭、异常处理等。
知道了上面这些,我们就可以尝试在自定义类里面创建__enter__()和__exit__()方法,来配合with语句创建类实例了:
class A: def __enter__(self): print('__enter__() is called') def __exit__(self, e_t, e_v, t_b): print('__exit__() is called') with A() as a: print('got instance')
输出:
另外python库中还有一个模块contextlib,使你不用构造含有__enter__, __exit__的类就可以使用with:
from __future__ import with_statement from contextlib import contextmanager @contextmanager def context(): print('entering the zone') try: yield except Exception as e: print('with an error %s'%e) raise e else: print('with no error') with context(): print('----in context call------')
输出:
相关文章推荐
- 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语句