上下文管理器


原理

上下文管理能保证资源会被正确回收,即保证退出步骤的执行。其用处最多的是,作为确保资源被正确回收的一种方式。

一种重复使用的 try-except-finally 结构的有效机制,因为其功能是封闭代码,且可以填充任意格式的代码块。

语法上 __enter__不接受其余参数,除了自带的self之外,__exit__在不包括self参数外,还包括三个参数(一个异常类型,一个异常实例和一个回溯),即exc_typeexc_instancetraceback,默认设置为None

可以通过让一个__exit__方法返回False实现异常传播,或者返回True终止异常。如果抛出另一个异常,将会代码原本的异常被发出去。

编写上下文的场景

  • 资源清理,例如打开数据库,打开文件等需要被正确关闭的资源
  • 避免重复

    1.传播异常

    2.终止异常

    3.处理特定异常类(实例4)

    4.不包括的子类(实例5)

原则1:简单的终止所有异常与try-except语句相同,但终止过多的错误会造成代码调试困难,一些隐含错误也会错误,造成过多的不确性。

代码讲解

实例1

# coding: utf-8

class ContextManager(object):
def __init__(self):
self.entered = False def __enter__(self):
self.entered = True
return self def __exit__(self, exc_type, exc_val, exc_tb):
self.entered = False cm = ContextManager() # 实例化一个对象,如果在其余地方不使用实例对象
# 写成 with ContextManager() as cm:
with cm:
print(cm.entered) # enter 方法返回对象,在 enter 作用范围内 self.enter 为 True print(cm.entered) # 执行了 exit 方法,返回的是 False

实例2

__exit__能处理异常,代码内引起的异常首先传给了__exit__并得到了正常的处理,返回False即异常被重新抛出给主模块,返回True则终止了异常在__exit__方法内

# coding: utf-8

class BubbleExceptions(object):
def __enter__(self):
return self def __exit__(self, exc_type, exc_val, exc_tb):
if exc_val:
print("Bubbing up exception: {}".format(exc_val))
return True with BubbleExceptions():
print(5/0)
"""
__exit__ 返回 False
Bubbing up exception: division by zero
Traceback (most recent call last):
File "/home/yuge/Documents/book/test.py", line 15, in <module>
print(5/0)
ZeroDivisionError: division by zero __exit__ 返回True
Bubbing up exception: division by zero
"""

实例3: 上下文内被正常处理的异常,不会发给__exit__

# coding: utf-8

class BubbleExceptions(object):
def __enter__(self):
return self def __exit__(self, exc_type, exc_val, exc_tb):
if exc_val:
print("Bubbing up exception: {}".format(exc_val))
return False with BubbleExceptions():
try:
print(5/0)
except ZeroDivisionError:
print("这是一个错误!") """
运行结果:
这是一个错误!
"""

实例4:__exit__可以处理特定异常类

即在__exit__方法里封装代码,将处理特定异常类的代码放进去,有点像try-except一样,最多的不同是,其代码可以重用。

# 处理特定的异常,并根据是否提起了其他异常类来决定是否返回 True 或 False
# coding: utf-8 class HandleValueError(object):
def __enter__(self):
return self def __exit__(self, exc_type, exc_val, exc_tb):
if not exc_type:
# 即没有异常出现
return True if issubclass(exc_type, ValueError):
print("捕捉到了一个 ValueError:{}".format(exc_val))
return True return False with HandleValueError():
# raise ValueError("错误的值!")
raise TypeError("错误的类型!") """
raise ValueError("错误的值!")
捕捉到了一个 ValueError:错误的值! raise TypeError("错误的类型!")
Traceback (most recent call last):
File "/home/yuge/Documents/book/test.py", line 22, in <module>
raise TypeError("错误的类型!")
TypeError: 错误的类型! """

实例5:如何处理特定的类,不处理其子类

# coding: utf-8

class ValueErrorSubclass(ValueError):
pass class HandleValueError(object):
def __enter__(self):
return self def __exit__(self, exc_type, exc_val, exc_tb):
if not exc_type:
return True # 这里只处理 ValueError 的错误,即不处理基类的子类
if exc_type == ValueError:
print("处理了一个 ValueError 的错误:{}".format(exc_val))
return True # if issubclass(exc_type, ValueError):
# # 这里处理了包括 基类的 所有类集体
# print("处理了基于 ValueError 的错误:{}".format(exc_val))
# return True return False with HandleValueError():
raise ValueErrorSubclass("这就是个失误") """
包括 issubclass
处理了基于 ValueError 的错误:这就是个失误 注释了 issubclass 之后
Traceback (most recent call last):
File "/home/yuge/Documents/book/test.py", line 30, in <module>
raise ValueErrorSubclass("这就是个失误")
__main__.ValueErrorSubclass: 这就是个失误
"""

python之简述上下文管理的更多相关文章

  1. python with语句上下文管理的两种实现方法

    在编程中会经常碰到这种情况:有一个特殊的语句块,在执行这个语句块之前需要先执行一些准备动作:当语句块执行完成后,需要继续执行一些收尾动作.例如,文件读写后需要关闭,数据库读写完毕需要关闭连接,资源的加 ...

  2. (转)Python中的上下文管理器和Tornado对其的巧妙应用

    原文:https://www.binss.me/blog/the-context-manager-of-python-and-the-applications-in-tornado/ 上下文是什么? ...

  3. Python之面向对象上下文管理协议

    Python之面向对象上下文管理协议 析构函数: import time class Open: def __init__(self,filepath,mode='r',encode='utf-8') ...

  4. Python深入02 上下文管理器

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

  5. Python中的上下文管理器和with语句

    Python2.5之后引入了上下文管理器(context manager),算是Python的黑魔法之一,它用于规定某个对象的使用范围.本文是针对于该功能的思考总结. 为什么需要上下文管理器? 首先, ...

  6. 深入理解 Python 中的上下文管理器

    提示:前面的内容较为基础,重点知识在后半段. with 这个关键字,对于每一学习Python的人,都不会陌生. 操作文本对象的时候,几乎所有的人都会让我们要用 with open ,这就是一个上下文管 ...

  7. 【Python】【上下文管理器】

    """#[备注]#1⃣️try :仅当try块中没有异常抛出时才运行else块.#2⃣️for:仅当for循环运行完毕(即for循环没有被break语句终止)才运行els ...

  8. python中实现上下文管理器的两种方法

    上下文管理器: python中实现了__enter__和__exit__方法的对象就可以称之为上下文管理器 实现方法一举例: def File(object): def __init__(self, ...

  9. python 描述符 上下文管理协议 类装饰器 property metaclass

    1.描述符 #!/usr/bin/python env # coding=utf-8 # 数据描述符__get__ __set__ __delete__ ''' 描述符总结 描述符是可以实现大部分py ...

随机推荐

  1. HDU 4511

    SHIT,SHIT,SHIT,SHIT,SHIT... 这道题可以使用AC自动机+DP来解决.也就是用非法路径建立TRIE图,然后从trie[root][1]点开始广搜DP即可.千万要注意一点,题目里 ...

  2. java SE与java EE , java ME之间的关系

    question: Which one should I install when I want to start learning Java? I'm going to start with som ...

  3. 【机房收费系统C#版】——导出Excel

    前言 机房合作開始好长了一段时间.反重复复开了几次会,项目也是一拖再拖,作为组长.有80%的责任都在于我.为了不让这个项目陪着我过春节.要求自己一定要在这几天敲完. 还是一样的问题,用C#敲,从一開始 ...

  4. ajax传对象或者数组到后端

    ajax是无法直接传送对象或者数组,有些人自己处理的话,能够把数据依照自己的标准连接成一个字符串,然后到后端处理.可是数据的不确定性.导致有可能会出错.并且麻烦 事实上有开源的包,能够直接解释成jso ...

  5. runtime objc_msgSend

    runtime objc_msgSend 字数1781 阅读245 评论2 喜欢7  前言 想要通过runtime发送消息,就必须要掌握runtime如何发送消息,是调用哪个函数?又是如何调用的?本篇 ...

  6. 学习Mockito - Mockito对Annotation的支持

    学习Mockito - Mockito对Annotation的支持 博客分类: test junit工作  Mockito支持对变量进行注解,例如将mock对象设为测试类的属性,然后通过注解的方式@M ...

  7. Windows10 显示库、隐藏6个目录、隐藏OneDrive

    Win10的资源管理器与之前的版本号最大的不同就是默认隐藏了库,又在此电脑中显示了6个用户目录. 但因为习惯了使用库进行文件的管理,这一改变有些令人不习惯. 以下就让我来教大家怎样显示库.以及隐藏这6 ...

  8. Selenium API 介绍

    Selenium API 介绍 我们先前学习过元素定位,大家不知道学习得怎么样了,当你学会元素定位之后就能够跟着我的脚步学习本节Selenium 经常使用的API 介绍 Seleium 为什么能模拟人 ...

  9. day63-webservice 11.cxf整合spring

    如果我们有Spring配置文件,怎么把WebService整合到Spring里面,用Ioc容器来管理这个Bean. 做项目的时候一般都是分层:Dao层.Service层.Service层要调Dao层, ...

  10. 乐字节-Java8核心特性实战-接口默认方法

    JAVA8已经发布很久,是自java5(2004年发布)之后Oracle发布的最重要的一个版本.其中包括语言.编译器.库.工具和JVM等诸多方面的新特性,对于国内外互联网公司来说,Java8是以后技术 ...