上下文管理器


原理

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

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

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

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

编写上下文的场景

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

    1.传播异常

    2.终止异常

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

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

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

代码讲解

实例1

  1. # coding: utf-8
  2. class ContextManager(object):
  3. def __init__(self):
  4. self.entered = False
  5. def __enter__(self):
  6. self.entered = True
  7. return self
  8. def __exit__(self, exc_type, exc_val, exc_tb):
  9. self.entered = False
  10. cm = ContextManager() # 实例化一个对象,如果在其余地方不使用实例对象
  11. # 写成 with ContextManager() as cm:
  12. with cm:
  13. print(cm.entered) # enter 方法返回对象,在 enter 作用范围内 self.enter 为 True
  14. print(cm.entered) # 执行了 exit 方法,返回的是 False

实例2

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

  1. # coding: utf-8
  2. class BubbleExceptions(object):
  3. def __enter__(self):
  4. return self
  5. def __exit__(self, exc_type, exc_val, exc_tb):
  6. if exc_val:
  7. print("Bubbing up exception: {}".format(exc_val))
  8. return True
  9. with BubbleExceptions():
  10. print(5/0)
  11. """
  12. __exit__ 返回 False
  13. Bubbing up exception: division by zero
  14. Traceback (most recent call last):
  15. File "/home/yuge/Documents/book/test.py", line 15, in <module>
  16. print(5/0)
  17. ZeroDivisionError: division by zero
  18. __exit__ 返回True
  19. Bubbing up exception: division by zero
  20. """

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

  1. # coding: utf-8
  2. class BubbleExceptions(object):
  3. def __enter__(self):
  4. return self
  5. def __exit__(self, exc_type, exc_val, exc_tb):
  6. if exc_val:
  7. print("Bubbing up exception: {}".format(exc_val))
  8. return False
  9. with BubbleExceptions():
  10. try:
  11. print(5/0)
  12. except ZeroDivisionError:
  13. print("这是一个错误!")
  14. """
  15. 运行结果:
  16. 这是一个错误!
  17. """

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

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

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

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

  1. # coding: utf-8
  2. class ValueErrorSubclass(ValueError):
  3. pass
  4. class HandleValueError(object):
  5. def __enter__(self):
  6. return self
  7. def __exit__(self, exc_type, exc_val, exc_tb):
  8. if not exc_type:
  9. return True
  10. # 这里只处理 ValueError 的错误,即不处理基类的子类
  11. if exc_type == ValueError:
  12. print("处理了一个 ValueError 的错误:{}".format(exc_val))
  13. return True
  14. # if issubclass(exc_type, ValueError):
  15. # # 这里处理了包括 基类的 所有类集体
  16. # print("处理了基于 ValueError 的错误:{}".format(exc_val))
  17. # return True
  18. return False
  19. with HandleValueError():
  20. raise ValueErrorSubclass("这就是个失误")
  21. """
  22. 包括 issubclass
  23. 处理了基于 ValueError 的错误:这就是个失误
  24. 注释了 issubclass 之后
  25. Traceback (most recent call last):
  26. File "/home/yuge/Documents/book/test.py", line 30, in <module>
  27. raise ValueErrorSubclass("这就是个失误")
  28. __main__.ValueErrorSubclass: 这就是个失误
  29. """

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. Spring Boot上传文件

    我们使用Spring Boot最新版本1.5.9.jdk使用1.8.tomcat8.0. <parent> <groupId>org.springframework.boot& ...

  2. Python学习-生成器 - Generator

    简单来说,generator是一个能够返回迭代器对象的函数. yield的使用: 在python中,当你定义一个函数,使用了yield关键字时,这个函数就是一个生成器,它的执行会和其他普通的函数有很多 ...

  3. HDU 5186

    easy !! #include <iostream> #include <cstdio> #include <algorithm> #define LL __in ...

  4. 自己定义控件三部曲之动画篇(七)——ObjectAnimator基本使用

    前言: 假如生活欺骗了你, 不要悲伤,不要心急! 忧郁的日子里须要镇静: 相信吧,快乐的日子终将会来临! 心儿永远向往着未来: 如今却常是忧郁. 一切都是瞬息,一切都将会过去: 而那过去了的,就会成为 ...

  5. cocos2dx 自己主动绑定js

    依照教程把全部资源下载好后....... 找到cocos2dx project下的tools/bindings-generator/test 发现里面有test.sh , test.ini , 去掉s ...

  6. 利用SQLite在android上创建数据库

    利用SQLite在android上创建数据库 方法: 1.创建我们的数据库类继承SQLiteOpenHelper类 完成相关函数的重写和数据库对象的初始化 public MySQLiteOpenHel ...

  7. hdoj--1258--Sum It Up(dfs)

    Sum It Up Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total ...

  8. 【HDU 1846】 Brave Game

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=1846 [算法] 巴什博弈 若有(m+1)个石子,显然先手不能直接取完,后手必胜 因此,我们可以把石 ...

  9. 【NOIP 2009】 Hankson的趣味题

    [题目链接] https://www.luogu.org/problemnew/show/P1072 [算法] x是b1的约数 筛出b1的约数,判断是否符合条件即可 [代码] #include< ...

  10. oracle连接数不够解决

    ora-12516: TNS: 监听程序找不到符合协议堆栈要求的可用处理程 看到如上错误出现,就要查看是否是是数据库连接数被占满了 具体的查询sql如下: select count(*) from v ...