我们看一个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------')

  输出:

最新文章

  1. Theoretical comparison between the Gini Index and Information Gain criteria
  2. MongoDB JAVA API Filters
  3. 百度翻译&&金山词霸API
  4. (转)Linux下安装Matlab2014及破解
  5. ExtJs布局大全
  6. JS面向对象组件(二)--Javascript原型链
  7. Leetcode - 186 Reverse Words in a String II
  8. Unity 3D Time 类
  9. Python各类并发模版
  10. mitmproxy实践
  11. go语言之进阶篇error接口应用
  12. flac3d自定义变量输出云图
  13. vue自定义日历组件的实现
  14. 铁乐学python26_hashlib+configparser+logging模块
  15. Art & Material
  16. RabbitMQ消息队列(五):Routing 消息路由[转]
  17. js省市二级联动
  18. python中的编解码小结
  19. 关于windows环境下cordova命令行无法启动adb.exe的解决办法
  20. jmeter-察看结果树-响应数据,中文显示乱码问题处理

热门文章

  1. Ubuntu12.04中安装Oracle JDK和NetBeans的方法
  2. Ubuntu12.04无法使用vim系统剪贴板解决方法
  3. thinkphp5 下 的Nginx 伪静态
  4. 重温CLR(十三) 定制特性
  5. 接口测试基础——第6篇unittest模块(三)
  6. kubectl&docker容器命令行窗口太小
  7. odoo 使用源码安装时的注意
  8. FastAdmin env.sample 的用法
  9. video4linux(v4l)使用摄像头的实例基础教程与体会(转)
  10. Docker安装ShowDoc