"""
#[备注]
#1⃣️try :仅当try块中没有异常抛出时才运行else块。
#2⃣️for:仅当for循环运行完毕(即for循环没有被break语句终止)才运行else
#while:仅当while循环因为条件为假植而退出时(即while循环没有被break语句终止)才运行else
#即在所有情况下,如果异常或者return、break、或continue语句导致控制权跳到了复合语句的主块之外,else子句也会被跳过 #15。2 上下文管理器和with块
#上下文管理协议包含__enter__和__exit__两个方法。with语句开始运行时,会在上下文管理器对象上调用__enter__方法。with语句运行结束后,会在上下文管理器对象上调用__exit__方法,以此扮演finally子句的角色
#例子15-1
with open('__init__.py') as fp:
src = fp.read(60)
print(len(src)) #4
print(fp) #<_io.TextIOWrapper name='__init__.py' mode='r' encoding='UTF-8'>
print(fp.closed,fp.encoding) #True UTF-8
print(fp.read(60)) #ValueError: I/O operation on closed file. #例子15-2 强调上下文管理器与__enter__方法返回的对象之间的区别
class LookingClass:
def __enter__(self):# 除了SELF外,python调用__enter__方法时不传入其他参数
import sys
self.original_write = sys.stdout.write #往标准输出里写入数据,相当于print
sys.stdout.write = self.reverse_write #为sys.stdout.write打猴子补丁
return 'JABBERWOCKY'
def reverse_write(self,text):
self.original_write(text[::-1])
def __exit__(self, exc_type, exc_val, exc_tb): #exc_type 异常类(例如ZeroDivisionError)exc_value 异常实例。有时会有参数传给异常构造方法,例如错误消息,这些参数可以使用exc_value.args获取 traceback :traceback对象。
import sys # 重复倒入模块不会消耗很多资源,因为python会缓存有导入的模块
sys.stdout.write = self.original_write #还原原来的sys.stdout.write方法
if exc_type is ZeroDivisionError:
print('Please DO NOT divide by zero!')
return True #告诉解释器,异常已经解决
#如果__exit__方法返回None,或者True之外的值,with块中的任何异常都会向上冒泡
with LookingClass() as what: #上下文管理器是LookingClass类的实例,python在上下文管理器上调用__enter__方法,把结果绑定到what上
print('Alice,Kigtty and Snowdrop') #pordwonS dna yttgiK,ecilA
print(what) #YKCOWREBBAJ
print(what) #JABBERWOCKY 输出不再反向
print('Back to normal.') #Back to normal. 输出不再反向
#例子15-4 在with块之外使用LookingClass类
manager = LookingClass()
print(manager) #<__main__.LookingClass object at 0x10d593be0>
monster = manager.__enter__()
print(monster == 'JABBERWOCKY') #eurT
print(monster) #YKCOWREBBAJ
print(manager) #>8abfca001x0 ta tcejbo ssalCgnikooL.__niam__<
manager.__exit__(None,None,None)
print(monster) #JABBERWOCKY ##15.3 contextlib模块中的实用工具
#closing :如果对象提供了close()方法,但没有实现__enter__/__exit__协议,那么可以实用这个函数构建上下文管理器
#suppress 构建临时忽略指定异常的上下文管理器
#@contextmanager 这个装饰器把简单的生成器函数变成上下文管理器,这样就不用创建类取实现管理器协议了
#15.4 使用@contextmanager
#例子15-5 使用生成器实现的上下文管理器
import contextlib @contextlib.contextmanager
def looking_glass():
import sys
original_write = sys.stdout.write def reverse_write(text):
original_write(text[::-1]) sys.stdout.write = reverse_write
yield 'JABBERWOCKY'
sys.stdout.write = original_write
#例子15-6 测试
with looking_glass() as what:
print('Alice,Kitty and Snowdrop') #pordwonS dna yttiK,ecilA
print(what) #YKCOWREBBAJ
print(what) #JABBERWOCKY
#[分析]其实,contextlib.contextmanager 装饰器会把函数包装成实现__enter__和__exit__方法的类。这个类的__enter__方法有如下作用
#...1⃣️调用生成器函数,保存生成器对象(这里把它称为gen)
#...2⃣️调用next(gen),执行到yield关键字所在的位置
#...3⃣️返回next(gen)产出的值,以便把产出的值绑定到with/as语句中的目标变量上。
#...with 块终止时,__exit__方法会作以下几件事
#...1⃣️检查有没有把异常传给exc_type;如果有,调用gen.throw(exception),在生成器函数定义体中包含yield关键字的那一行抛出异常
#...2⃣️否则,嗲用next(gen),继续执行生成器函数定义体中yield之后的代码
#【注意】上面的例子有一个严重的错误:如果发生异常,python解释器会将其捕获,然后在looking_glass函数的yield表达式里再次抛出。但是,那里没有处理错误的代码,因此looking_glass函数会中止,永远无法恢复成原来的sys.stdout.write方法,导致系统处于无效状态
# 例子15-7 基于生成器的上下文管理器,而且实现了异常处理- """ import contextlib
@contextlib.contextmanager
def looking_glass():
import sys
original_write = sys.stdout.write def reverse_write(text):
original_write([text[::-1]]) sys.stdout.write = reverse_write msg = ''
try:
yield 'JABBERWOCKY'
except ZeroDivisionError :
msg = 'Please DO NOT divede by zero!'
finally:
sys.stdout.write = original_write
if msg:
print(msg)

【Python】【上下文管理器】的更多相关文章

  1. python 上下文管理器

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 上下文管理器(context manager)是Python2.5开始支持的一种语 ...

  2. Python 上下文管理器和else块

    最终,上下文管理器可能几乎与子程序(subroutine)本身一样重要.目前,我们只了解了上下文管理器的皮毛--Basic 语言有with 语句,而且很多语言都有.但是,在各种语言中 with 语句的 ...

  3. Python上下文管理器

    在Python中让自己创建的函数.类.对象支持with语句,就实现了上线文管理协议.我们经常使用with open(file, "a+") as f:这样的语句,无需手动调用f.c ...

  4. python上下文管理器ContextLib及with语句

    http://blog.csdn.net/pipisorry/article/details/50444736 with语句 with语句是从 Python 2.5 开始引入的一种与异常处理相关的功能 ...

  5. Python上下文管理器 with

    对于系统资源的操作,如:文件操作.数据库操作等,我们往往打开文件.连接数据库后忘了将其close掉,这时就可能会引发异常,因此我们常用的做法是: # coding:utf-8 f = open(&qu ...

  6. Python上下文管理器(Context managers)

    上下文管理器(Context managers) 上下文管理器允许你在有需要的时候,精确地分配和释放资源. 使用上下文管理器最广泛的案例就是with语句了.想象下你有两个需要结对执行的相关操作,然后还 ...

  7. python上下文管理器细读

    test 1 上下文管理器,将生成器转化为上下文管理器 import contextlib @contextlib.contextmanager def a(): print(1) yield pri ...

  8. 吃透Python上下文管理器

    什么是上下文管理器? 我们常见的with open操作文件,就是一个上下文管理器.如: with open(file, 'rb') as f: text = f.read() 那上下文管理器具体的定义 ...

  9. python 上下文管理器contextlib.ContextManager

    1 模块简介 在数年前,Python 2.5 加入了一个非常特殊的关键字,就是with.with语句允许开发者创建上下文管理器.什么是上下文管理器?上下文管理器就是允许你可以自动地开始和结束一些事情. ...

  10. Python 上下文管理器模块--contextlib

    在 Python 处理文件的时候我们使用 with 关键词来进行文件的资源关闭,但是并不是只有文件操作才能使用 with 语句.今天就让我们一起学习 Python 中的上下文管理 contextlib ...

随机推荐

  1. Vue 过渡

    过渡 通过 Vue.js 的过渡系统,可以在元素从 DOM 中插入或移除时自动应用过渡效果.Vue.js 会在适当的时机为你触发 CSS 过渡或动画,你也可以提供相应的 JavaScript 钩子函数 ...

  2. OpenCV中PCA实现人脸降维

    前言: PCA是大家经常用来减少数据集的维数,同时保留数据集中对方差贡献最大的特征来达到简化数据集的目的.本文通过使用PCA来提取人脸中的特征脸这个例子,来熟悉下在oepncv中怎样使用PCA这个类. ...

  3. Fiddler抓包域名过滤

    Fiddler抓包域名过滤 我们在用Fiddler抓包的时候会抓到很多不需要的数据包,我们怎样才能过滤掉不想要的域名只显示自己想要的域名? 通过Fiddler域名过滤可以解决这一问题! 下面是只显示想 ...

  4. memset函数使用方法

    将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值, 块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作, 其返回值为指向S的指针. 需要的头文件 在C中 < ...

  5. Qt QDataTime QString 两个类的使用

    QDateTime now = QDateTime::currentDateTime(); QString nowStr; nowStr = now.toString("yyyyMMdd_h ...

  6. sql 关于存储过程的查询

    --查数据库中所有的存储过程select * from sys.procedures ----------------------查数据库中所有的存储过程select o.name from sysc ...

  7. typed.js

    实现效果,文字逐个输出. 实例代码: <script> $(function(){ $("#head-title").typed({ strings: ["为 ...

  8. Code Blocks+gtest环境配置

    本文仅介绍Code::Blocks+gtest环境配置,gtest具体使用方法请参考: 玩转Google开源C++单元测试框架Google Test系列(gtest)(总) http://www.cn ...

  9. 20145316《网络对抗》Exp9 Web安全基础实践学习总结

    20145316<网络对抗>Exp9 Web安全基础实践学习总结 基础问题回答 SQL注入攻击原理,如何防御 SQL注入,就是攻击者通过把SQL命令插入到Web表单递交或输入域名或页面请求 ...

  10. 利用arcgis处理遥感栅格数据,得到省平均值数据

    1.准备全国省级行政区数据,需要有省级行政区信息,如下所示: 2.生成渔网数据,操作完成会生成一个面数据和一个点数据,我们主要用点数据进行后面的操作. 3.提取栅格数据的值到渔网点数据中. 4.将区域 ...