Python中的上下文管理器和with语句的使用


Posted in Python onApril 17, 2018

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

为什么需要上下文管理器?

首先,需要思索下为什么需要引入上下文管理器。

在正常情况下,管理各种系统资源(如文件)、数据库连接时,通常是先打开这些资源,执行完相应的业务逻辑,最后关闭资源。

举两个例子:

1.使用Python打开一个文件写入内容,之后需要关闭这个文件。如果不正常关闭的话可能会在文件操作时出现异常,因为系统允许你打开的文件的最大数是有限的。

2.在数据库连接时也是存在类似问题,数据库的连接算是一种比较昂贵的资源,若连接过多而没有及时关闭的话,就可能出现不能继续连接的异常错误。

但是,很多程序员经常会忘记关闭文件,或者关闭数据库的连接。这时候就引入了上下文管理器,它可以在你不需要该对象的时候,自动关闭它。

上下文管理器怎么使用?

上下文管理器的语法是:with...as...

实例:文件操作

print "不使用上下文管理器"
print "*" * 30
f = open('file.py', 'w')
print f.closed
f.write("# Hello World")
f.close()
print f.closed

print "\n使用上下文管理器"
print "*" * 30
with open("file.py", 'w') as f:
  print f.closed
  f.write('# Hello Python')
print f.closed

这里通过.closed比较,我们可以看到上下文管理器可以自动关闭文件,对于上下文管理器而言,有隶属于它的程序块,当隶属于它的程序块执行结束的时候(判断缩进),上下文管理器将自动关闭文件。
 上述实例,也可以使用try...except...来实现,同样可以很直观的看到使用with...as...语句之后,代码确实相对更加简洁。

上下文管理实现机制

因为文件对象是Python的内置对象,内置了上下文管理的特殊方法,所以它可以使用with语句。在Python中,任何对象,只要实现了上下文管理,就可以使用with语句,实现上下文管理需要通过__enter__和__exit__这两个方法来实现。

关于这两个方法:

  1. enter(self):进入该对象时调用此方法,返回值将放入with...as...语句中的as说明的变量中
  2. exit(self, type, value, tb):离开上下文管理器时调用该方法,如果有异常出现,返回False,type、value和tb将分别表示异常的类型、值和追踪信息,传递出上下文显示;如果没有异常,则三个变量的值均为None。

with 上下文管理器:
    语法体

当with语句遇到上下文管理器时,就会在执行语法体之前,先执行__enter__方法,然后再执行语法体,执行完语法体之后,执行__exit__方法。

上下文管理器实现

使用Python2.7X实现一个上下文管理器:

class Context(object):

  def __init__(self):
    print "实例化一个对象"

  def __enter__(self):
    print "获取该对象"

  def __exit__(self, exc_type, exc_val, exc_tb):
    print "退出该对象"

temp = Context()

with temp:
  print "执行体"

这样,__enter__方法和__exit__方法的调用过程就很明晰。

contextLib

在contextlib中,提供了contextmanager装饰器,通过yield返回函数将函数分隔为两部分,yield之前的语句在__enter__中执行,yield之后的语句在__exit__中执行,简化了上下文管理器的实现方式:

总结:通过上下文管理器,我们可以更好的控制对象在不同区间的特性,并且可以使用with语句替代try...except方法,使得代码更加的简洁,主要的使用场景是访问资源,可以保证不管过程中是否发生错误或者异常都会执行相应的清理操作,释放出访问的资源。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python运行的17个时新手常见错误小结
Aug 07 Python
python正则表达式re模块详细介绍
May 29 Python
Python的Django框架中的URL配置与松耦合
Jul 15 Python
Python学习小技巧之利用字典的默认行为
May 20 Python
Python导入模块时遇到的错误分析
Aug 30 Python
python分布式环境下的限流器的示例
Oct 26 Python
分享6个隐藏的python功能
Dec 07 Python
Python cookbook(数据结构与算法)字典相关计算问题示例
Feb 18 Python
在OpenCV里使用特征匹配和单映射变换的代码详解
Oct 23 Python
Python hashlib模块实例使用详解
Dec 24 Python
Python安装与卸载流程详细步骤(图解)
Feb 20 Python
python小程序基于Jupyter实现天气查询的方法
Mar 27 Python
Python实现读取字符串按列分配后按行输出示例
Apr 17 #Python
一个简单的python爬虫程序 爬取豆瓣热度Top100以内的电影信息
Apr 17 #Python
Numpy掩码式数组详解
Apr 17 #Python
对numpy中布尔型数组的处理方法详解
Apr 17 #Python
Python简单实现阿拉伯数字和罗马数字的互相转换功能示例
Apr 17 #Python
python3库numpy数组属性的查看方法
Apr 17 #Python
对python中的for循环和range内置函数详解
Apr 17 #Python
You might like
用PHP制作静态网站的模板框架(二)
2006/10/09 PHP
用php+mysql一个名片库程序
2006/10/09 PHP
解决中英文字符串长度问题函数
2007/01/16 PHP
使用YUI+Ant 实现JS CSS压缩
2014/09/02 PHP
Yii框架中memcache用法实例
2014/12/03 PHP
php内存缓存实现方法
2015/01/24 PHP
Laravel 验证码认证学习记录小结
2019/12/20 PHP
[原创]静态页面也可以实现预览 列表不同的显示方式
2006/10/14 Javascript
使用jquery给input和textarea设定ie中的focus
2008/05/29 Javascript
JavaScript:Div层拖动效果实例代码
2013/08/06 Javascript
JavaScript中通过prototype属性共享属性和方法的技巧实例
2015/03/13 Javascript
DOM操作原生js 的bug,使用jQuery 可以消除的解决方法
2016/09/04 Javascript
JS简单实现浮动窗口效果示例
2016/09/07 Javascript
jquery购物车结算功能实现方法
2020/10/29 Javascript
JavaScript三种绑定事件方式及相互之间的区别分析
2017/01/10 Javascript
JavaScript使用delete删除数组元素用法示例【数组长度不变】
2017/01/17 Javascript
初探nodeJS
2017/01/24 NodeJs
利用types增强vscode中js代码提示功能详解
2017/07/07 Javascript
vue.js项目中实用的小技巧汇总
2017/11/29 Javascript
解决vue 中 echart 在子组件中只显示一次的问题
2018/08/07 Javascript
在 Angular-cli 中使用 simple-mock 实现前端开发 API Mock 接口数据模拟功能的方法
2018/11/28 Javascript
JS前后端实现身份证号验证代码解析
2020/07/23 Javascript
[56:14]Fnatic vs OG 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
[01:51]历届DOTA2国际邀请赛举办地回顾 TI9落地上海
2018/08/26 DOTA
判断python字典中key是否存在的两种方法
2018/08/10 Python
python print出共轭复数的方法详解
2019/06/25 Python
Python APScheduler执行使用方法详解
2020/12/10 Python
HTML5的Geolocation地理位置定位API使用教程
2016/05/12 HTML / CSS
什么是用户模式(User Mode)与内核模式(Kernel Mode) ?
2014/07/21 面试题
2014年三八妇女节活动方案
2014/02/28 职场文书
小学师德师风演讲稿
2014/09/02 职场文书
2015年校长新年寄语
2014/12/08 职场文书
初中化学教学反思
2016/02/22 职场文书
2016年妇联“6﹒26国际禁毒日”宣传活动总结
2016/04/05 职场文书
利用 Python 的 Pandas和 NumPy 库来清理数据
2022/04/13 Python
蓝牙耳机怎么连接电脑win11? Win11蓝牙耳机连接电脑的技巧
2023/01/09 数码科技