Python with上下文管理及自定义上下文管理

一、上下文管理器

上下文管理器是对Context Manager的翻译 ,上下文是 context 直译的叫法,在程序中用来表示代码执行过程中所处的前后环境.

在文件操作时,需要打开,关闭文件,而在文件在进行读写操作时,就是处在文件操作的上下文中,也就是文件操作环境中.

语法: with

with 语句是 Pyhton 提供的一种简化语法,从Python 2.5 开始引入的一种与异常处理相关的功能,适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“扫尾”操作,释放资源.

比如文件使用后自动关闭、数据库连接的自动关闭等.

二、with上下文管理器示例

with open('test.txt', 'a') as f:f.write('上下文管理\n')

运行以上代码,会在代码同级目录下创建一个叫test.txt的文本文件,并在文件中追加内容"上下文管理",并换行.

在执行 with 语句时,首先执行 with 后面的 open 代码(如果已经有test.txt文件则打开,如果没有test.txt文件则创建),然后通过as将代码的结果保存到 f 中(相当于给test.txt起个别名f,f只是一个变量名,您可以自定义)

在with下面是对test.txt执行的操作,如示例中的操作是写入内容.

在操作后,不需要对文件test.txt进行关闭操作f.close(),with上下文管理器会在文件使用完后帮我们关闭test.txt文件.

这么做即可以简化代码,又可以避免因粗心忘记执行关闭操作而出现异常,因为在实际开发中,打开一个文件后,进行的操作可能非常复杂,这种情况是很可能忘记做"扫尾"操作的.

三、with上下文管理的原理

在使用with上下文管理器时,并不是不需要关闭文件,而是文件的关闭操作在 with 的上下文管理器中已经实现了.当文件操作执行完成后,with语句会自动调用上下文管理器里的关闭语句来关闭文件资源.

我们的应用场景并不是一成必变,with是怎么实现帮我们做"扫尾"操作的呢?

with语句在执行时,调用上下文管理器中的 __enter__ 和 __exit__ 两个方法,这两个方法就是上下文管理器中实现的方法.

__enter__ 方法会在执行with后面的语句时执行,一般用来处理操作前的内容.比如打开文件,创建对象,初始化等.

__exit__ 方法会在with内的代码执行完毕后执行,一般用来处理一些善后收尾工作,比如文件的关闭,数据库的关闭等.

四、自定义上下文管理器

根据上下文管理的原理,上下文管理器的原理是实现了__enter__和__exit__这两个方法,所以我们可以根据此原理来自定义自己的上下文管理器.

在自定义上下文管理器时,只要在类中实现 __enter__ 和 __exit__ 两个方法即可.

class OpenFile(object):"""自定义上下文管理类"""def __init__(self, file, mode):self._file = fileself._mode = modedef __enter__(self):print('__enter__  打开文件')self._handle = open(self._file, self._mode)return self._handledef __exit__(self, exc_type, exc_val, exc_tb):print('__exit__ 关闭文件')self._handle.close()with OpenFile('test01.txt', 'w') as f:f.write('自定义上下文管理\n')

上面的代码中,我们不是使用Python实现好的open来打开文件,而是通过自定义的OpenFile类来完成文件的操作.

代码运行过程和结果与用open类似,会先执行OpenFile后的代码(自定义类OpenFile中的代码),如果存在文件test01.txt,打开文件并在其中写入"自定义上下文管理",如果不存在文件test01.txt,则创建文件并写入"自定义上下文管理".

说明我们成功实现了自定义上下文管理.

五、上下文管理中的自定义异常处理

我们看到,__exit__ 方法中有三个参数exc_type ,exc_val 和exc_tb ,这三个参数是用来接收异常信息的,如果代码在运行时发生异常,异常信息会被保存到这三个参数中.

class OpenFile(object):"""自定义上下文管理类"""def __init__(self, file, mode):self._file = fileself._mode = modedef __enter__(self):self._handle = open(self._file, self._mode)return self._handledef __exit__(self, exc_type, exc_val, exc_tb):print('Type: ', exc_type)print('Value:', exc_val)print('TreacBack:', exc_tb)self._handle.close()with OpenFile('test01.txt', 'r') as f:f.write('自定义上下文管理\n')

上面的代码中,传入的'w'换成了'r',会出现异常,因为以读的模式打开文件,不能进行写操作.运行结果为:

Traceback (most recent call last):
Type:  <class 'io.UnsupportedOperation'>File "python_demo/with_demo.py", line 45, in <module>
Value: not writablef.write('自定义上下文管理\n')
TreacBack: <traceback object at 0x0000024EA5E11508>
io.UnsupportedOperation: not writable

可以看到我们打印的三个参数exc_type ,exc_val 和exc_tb的值.分别存储了异常的以下信息:

exc_type : 异常类型

exc_val : 异常值

exc_tb : 异常回溯追踪

当with中执行的语句发生异常时,异常信息会被发送到 __exit__ 方法的参数中,这时可以根据情况选择如何处理异常.

因为在 __exit__函数执行异常处理时,会根据函数的返回值决定是否将系统抛出的异常继续向外抛出.如果返回值为 False 就会向外抛出,用户就会看到.如果返回值为 True 不会向外抛出,而是显示我们自定义的信息.

我们可以根据这个原理自定义如何处理异常,只要将返回值设置为True就行了.

class OpenFile(object):"""自定义上下文管理类"""def __init__(self, file, mode):self._file = fileself._mode = modedef __enter__(self):self._handle = open(self._file, self._mode)return self._handledef __exit__(self, exc_type, exc_val, exc_tb):self._handle.close()# 通过exc_type参数接收到的值,来判断程序执行是否出现异常# 如果是None,说明没有异常if exc_type == "None":print('正常执行')else:# 否则出现异常,可以选择怎么处理异常print(exc_type, exc_val)# 返回值决定了捕获的异常是否继续向外抛出# 如果是False那么就会继续向外抛出,程序会看到系统提示的异常信息# 如果是True不会向外抛出,程序看不到系统提示信息,只能看到else中的输出return Truewith OpenFile('test01.txt', 'r') as f:f.write('自定义上下文管理\n')

通过设置返回值为True,上下文管理器不会向外抛出异常,此时我们在根据exc_type(异常类型)的值是否为"None"来自定义输出的异常信息,就可以实现上下文管理中的自定义异常了.

Python with上下文管理及自定义上下文管理相关推荐

  1. Shiro结合redis的统一会话管理:自定义会话管理器

    Shiro结合redis的统一会话管理 步骤分析 构建环境 (1)使用开源组件Shiro-Redis可以方便的构建shiro与redis的整合工程. <dependency><gro ...

  2. python语言使用什么语句实现上下文管理协议_Python with语句上下文管理器两种实现方法分析...

    本文实例讲述了Python with语句上下文管理器.分享给大家供大家参考,具体如下: 在编程中会经常碰到这种情况:有一个特殊的语句块,在执行这个语句块之前需要先执行一些准备动作:当语句块执行完成后, ...

  3. python语言使用什么语句实现上下文管理协议_Python 上下文管理器

    上下文管理器 在使用Python编程中,可以会经常碰到这种情况:有一个特殊的语句块,在执行这个语句块之前需要先执行一些准备动作:当语句块执行完成后,需要继续执行一些收尾动作. 例如:当需要操作文件或数 ...

  4. python语言使用什么语句实现上下文管理协议_Python 技巧探究:上下文管理器和with语句...

    一:前言 Python 里面的 with 语句是被认为是晦涩难懂的特征之一,但是当你窥视它的内部你就会发现这里面并没有什么魔法.事实上它可以帮助我们写一些整洁和可读性高的代码. 那么 with 语句适 ...

  5. Python入门:ChainMap 有效管理多个上下文

    摘要: Python的ChainMap从collections模块提供用于管理多个词典作为单个的有效工具. 本文分享自华为云社区<从零开始学python | ChainMap 有效管理多个上下文 ...

  6. python的上下文管理用哪个关键字_正确理解python中的关键字“with”与上下文管理器...

    正确理解python中的关键字"with"与上下文管理器 来源:中文源码网    浏览: 次    日期:2018年9月2日 [下载文档:  正确理解python中的关键字&quo ...

  7. 文件处理,文件的三种打开模式,绝对路劲和相对路径,with管理网文件上下文,文件的高级应用,文件的修改,登陆注册。...

    1.文件处理 什么是文件处理:修改存储的信息. 什么是文件:操作系统提供的虚拟概念,存储信息(用二进制存储信息) 操作核心是:读和写. 1.1操作文件的流程: 1.打开文件流程:1.文件路径" ...

  8. python筛选时间段_django admin管理工具自定义时间区间筛选器DateRangeFilter介绍

    django admin管理工具有很多好用的功能,例如搜索框.筛选器等,编码简单,功能强大. 但是常规的时间筛选有一定局限性,只能显示一定时间节点到当前时间这一段时间段内的筛选结果,做不到自由定义时间 ...

  9. python cms建站教程:Wagtail建站(二、修改主页与自定义后台管理)

    不得不说python的中文cms建站教程实在是太少了,直接用Django/Flask这样的框架从头开始写又实在是有点麻烦,自己摸索着写一点使用Wagtail建站的方法,仅供参考.Wagtail是一款基 ...

最新文章

  1. 如何从0到1打造一款AI产品?
  2. python解压版怎么安装不了_python 连接数据库mysql解压版安装配置及遇到问题
  3. Matlab注释语句
  4. 图像处理之直方图均衡MATLAB代码实现
  5. SpringMVC 学习系列 (4) 之 数据绑定 -1
  6. hibernate添加spring 事务管理注意问题记录
  7. echart高级使用_Echart使用总结
  8. 电脑开机显示服务器启动失败是什么原因,请问我的电脑在启动时显示NTDETECT失败是什么意思? 爱问知识人...
  9. spacy model
  10. 超融合平台安装oracle,超融合平台集成实施方案
  11. M1卡说明及使用proxmark3破解方法
  12. python基本代码教程-python基础教程
  13. 高效率实现web自动完成功能-三叉搜索树
  14. [论文笔记]FusionNet: Fusing via Fully-Aware Attention with Application to Machine Comprehension
  15. 游戏开发之动态创建对象及构造函数、析构函数的执行(C++基础)
  16. python3连接到sql server数据库,检查是否存在某个数据库,没有则创建
  17. 2018中科院计算所夏令营面试经历
  18. 在图3-30 中,某学院的以太网交换机有三个接口分别和学院三个系的以太网相连,另外三个接口分别和电子邮件服务器、万维网服务器以及一个连接互联网的路由器相连。图中的A,B和C都是100Mbit/s以太网
  19. java多项式加法与乘法_java多项式加减法
  20. 最美圣诞树,用Python画棵雪夜圣诞树送给你

热门文章

  1. Java异常类复习总结
  2. HashMap 和 Hashtable 的同和不同
  3. Winform开发框架中工作流模块之申请单草稿处理
  4. iOS开发 适配iOS10以及Xcode8-b
  5. Tiny之7*24集群服务方案
  6. lintcode 中等题:Single number III 落单的数III
  7. PL/SQL Developer SQL Window中不能插入多条数据
  8. 学点 C 语言(38): 函数 - 函数指针
  9. jQuery 源码解析(三十一) 动画模块 便捷动画详解
  10. 04737 c++ 自学考试2019版 第四章课后程序设计题1