流畅python学习笔记:第十五章:上下文管理器
在开始本章之前,我们首先来谈谈try…excep..final模块.在Python中,进行异常保护的最多就是用try..except..final.首先来看下下面的代码。进行一个简单的除法运算。为了防止分母为0.所以用到了try…except…finally模块
def get_result():
a=3
b=0
try:
b=3/0 #函数主体运算代码
except BaseException,e: #当发生异常的时候,跳到这执行
print e
finally: #不管是否发生异常,都执行finally语句
print b
if __name__=="__main__":
get_result()
E:\python2.7.11\python.exe E:/py_prj/fluent_python/chapter15.py
integer division or modulo by zero
0
从结果可以看出,打印出了integer division or modulo by zero的失败信息。但是在上面的代码中分支还是太多,有没有一种更为简洁的方法来达到这个效果呢。这就是本章要介绍的with模块。
我们经常看到python书上在打开文件进行读取的时候代码是下面的样子,并且推荐这样写。原因是能够释放资源,比如在文件用完后自动关闭文件。
with open('filename','wt') as f:
f.write("hello world")
如果我们不用with,那么代码就得按照下面的方式写。代码分支更多一些
file=open('filename','wt')
try:
data=file.read()
finally:
file.close()
那么with语句的工作原理是什么呢? 主要是两个模块 __enter__和__exit__。工作流程主要是2步:
1 紧跟with后面的语句被求值后,返回对象的__enter__()方法被调用,这个方法的返回值将被赋值给as后面的变量
2 当with后面的代码块全部被执行完之后,将调用前面返回对象的__exit__()方法
来看下代码的实现:
class try_with(object):
def __enter__(self):
print "in __enter__"
return "__enter__"
def __exit__(self, exc_type, exc_val, exc_tb):
print "in __exit__"
if __name__=="__main__":
with try_with() as t:
print "in __main__"
print t
E:\python2.7.11\python.exe E:/py_prj/fluent_python/chapter15.py
in __enter__
in __main__
__enter__
in __exit__
从执行结果可以看到,首先执行了__enter__,返回”__enter__”并且赋值给t. 然后执行with as后面的代码段。当执行完了后,执行__exit__。另外在__exit__中还有3个参数:exc_type,exc_val,exc_tb. 这些参数是异常场景下才会使用的,我们来把代码修改下:
class try_with(object):
def __enter__(self):
print "in __enter__"
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print "type:%s" % exc_type
print "val:%s" % exc_val
print "tb:%s" % exc_tb
print "in __exit__"
def calculate(self):
ret=1/0
print ret
if __name__=="__main__":
with try_with() as t:
print "in __main__"
print t.calculate()
E:\python2.7.11\python.exe E:/py_prj/fluent_python/chapter15.py
in __enter__
in __main__
type:<type 'exceptions.ZeroDivisionError'>
val:integer division or modulo by zero
tb:<traceback object at 0x017F2030>
in __exit__
Traceback (most recent call last):
File "E:/py_prj/fluent_python/chapter15.py", line 31, in <module>
print t.calculate()
File "E:/py_prj/fluent_python/chapter15.py", line 13, in calculate
ret=1/0
ZeroDivisionError: integer division or modulo by zero
从结果可以看出:实际上,在with后面的代码块抛出任何异常时,__exit__()方法被执行。正如例子所示,异常抛出时,与之关联的type,value和stack trace传给__exit__()方法,因此抛出的ZeroDivisionError异常被打印出来了。开发库时,清理资源,关闭文件等等操作,都可以放在__exit__方法当中。因此,Python的with语句是提供一个有效的机制,让代码更简练,同时在异常产生时,清理工作更简单。
看到这里我们再回想下之前的文件打开代码,这时可以理解了为什么书中都推荐用with打开。在open中其实是实现了__enter__和__exit__语句来保障文件的正确打开和关闭
with open('filename','wt') as f:
f.write("hello world")
那么我们是否可以自定义一个上下文管理器呢?这里python也提供了模块让我们来自定义,这就是@contextmanager装饰器。我们来看下代码@contextmanagdef file_open(path)
try:
f=open('filename','wt')
yield f
except BaseException,e
print e
finally:
print 'close file'
f.close() if __name__=="__main__":
with file_open() as file_obj:
file_obj.write("hello world")
我们从contextlib模块中引入contextmanager,然后装饰我们所定义的file_open函数。这就允许我们使用Python的with语句来调用file_open函数。在函数中,我们打开文件,然后通过yield,将其传递出去,最终主调函数可以使用它。
一旦with语句结束,控制就会返回给file_open函数,它继续执行yield语句后面的代码。这个最终会执行finally语句--关闭文件。如果我们在打开文件时遇到了OSError错误,它就会被捕获,最终finally语句依然会关闭文件句柄。
流畅python学习笔记:第十五章:上下文管理器的更多相关文章
- 流畅的python第十五章上下文管理器和else块学习记录
with 语句和上下文管理器for.while 和 try 语句的 else 子句 with 语句会设置一个临时的上下文,交给上下文管理器对象控制,并且负责清理上下文.这么做能避免错误并减少样板代码, ...
- 【Python学习笔记】with语句与上下文管理器
with语句 上下文管理器 contextlib模块 参考引用 with语句 with语句时在Python2.6中出现的新语句.在Python2.6以前,要正确的处理涉及到异常的资源管理时,需要使用t ...
- Python学习笔记(十五):类基础
以Mark Lutz著的<Python学习手册>为教程,每天花1个小时左右时间学习,争取两周完成. --- 写在前面的话 2013-7-24 23:59 学习笔记 1,Python中的大多 ...
- 流畅的python学习笔记:第五章
在python中一切都可以视作为对象,包括函数.我们来看个例子: def function_try(): '''it is funciton try doc''' print 'fun ...
- Python学习笔记第二十五周(Django补充)
1.render_to_reponse() 不同于render,render_to_response()不用包含request,直接写template中文件 2.locals() 如果views文件中 ...
- 流畅python学习笔记:第十一章:抽象基类
__getitem__实现可迭代对象.要将一个对象变成一个可迭代的对象,通常都要实现__iter__.但是如果没有__iter__的话,实现了__getitem__也可以实现迭代.我们还是用第一章扑克 ...
- 流畅python学习笔记:第十七章:并发处理
第十七章:并发处理 本章主要讨论Python3引入的concurrent.futures模块.在python2.7中需要用pip install futures来安装.concurrent.futur ...
- Python学习笔记第十五周
目录: 一.CSS补充 1.position 2.overflow 3.hover 4.background 二.JavaScript 三.DOM 主要内容: 一.CSS补充 1.position 可 ...
- 流畅python学习笔记:第十七章:并发处理二
本章讨论python3.2引入的concurrent.futures模块.future是中文名叫期物.期物是一种对象,表示异步执行的操作 在很多任务中,特别是处理网络I/O.需要使用并发,因为网络有很 ...
- 学习笔记 第十五章 JavaScript基础
第15章 JavaScript基础 [学习重点] 了解JavaScript基础知识 熟悉常量和变量 能够使用表达式和运算符 正确使用语句 能够掌握数据类型和转换的基本方法 正确使用函数.对象.数组 ...
随机推荐
- 如何判断img标签是否有src属性
前几天,写一个小项目,需要判断img标签是否有src属性,想了半天,只能想到用jq实现,如下: if($(".img").attr("src")==undefi ...
- JavaScript对象之document对象
DOM对象之document对象 DOM对象:当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model). HTML DOM 模型被构造为对象的树. 打开网页后,首先 ...
- 编译安装nginx却requires the PCRE library
编译安装nginx需要pcre包,未安装会有如下提示: ./configure: error: the HTTP rewrite module requires the PCRE library. Y ...
- PHPCMS V9表单向导调用及分页
参考资料如下:v9_form_tlj为你的表单数据表,`flqh`,`title`,`sj`,`username`,`datetime` 为你表单内的字段,page="$_GET" ...
- javascript中的构造函数和继承
1.第一节 使用工厂模式创建一个构造函数CreatePerson function CreatePerson(name,sex){//构造函数:用于构造对象 可以说在js里类就是构造函数 //1.原料 ...
- 20170422早会训话,ps:程序出现两次BUG,领导很生气
针对这种问题: 要讲3点 1.有没有拖团队后腿: 作为一名前端开发人员,对于前端开发的任务,我能够在第一时间完成,保证时间进度,但光做到这一点是不够的,不能只讲究任务,不考虑结果,会不会出现问题造成其 ...
- 不支持placeholder浏览器下对placeholder进行处理
if(document.createElement('input').placeholder !== '') { $('[placeholder]').focus(function() { var i ...
- Mybatis传参方式
Mybatis传多个参数(三种解决方案) 据我目前接触到的传多个参数的方案有三种. 第一种方案 DAO层的函数方法 ? 1 Public User selectUser(String name,St ...
- ECMAScript 6 中的快捷语法汇总及代码示例
对于每个 JavaScript 开发人员,快捷语法都是必备技能之一,下面就集中介绍这些快捷语法. 三元运算符 传统写法 const x = 20; let answer; if (x > 10) ...
- 实现excel导入导出功能,excel导入数据到页面中,页面数据导出生成excel文件
今天接到项目中的一个功能,要实现excel的导入,导出功能.这个看起来思路比较清楚,但是做起了就遇到了不少问题. 不过核心的问题,大家也不会遇到了.每个项目前台页面,以及数据填充方式都不一样,不过大多 ...