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 相关文章推荐
linux系统使用python获取内存使用信息脚本分享
Jan 15 Python
Python的re模块正则表达式操作
May 25 Python
TensorFlow实现随机训练和批量训练的方法
Apr 28 Python
对django中render()与render_to_response()的区别详解
Oct 16 Python
Python利用递归实现文件的复制方法
Oct 27 Python
详解PyCharm安装MicroPython插件的教程
Jun 24 Python
Django models.py应用实现过程详解
Jul 29 Python
python打印文件的前几行或最后几行教程
Feb 13 Python
selenium+python配置chrome浏览器的选项的实现
Mar 18 Python
Python3.7.0 Shell添加清屏快捷键的实现示例
Mar 23 Python
Pycharm 2020.1 版配置优化的详细教程
Aug 07 Python
Python3自带工具2to3.py 转换 Python2.x 代码到Python3的操作
Mar 03 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 文章中的远程图片采集到本地的代码
2009/07/30 PHP
网页上facebook分享功能具体实现
2014/01/26 PHP
destoon数据库表说明汇总
2014/07/15 PHP
php实现在限定区域里自动调整字体大小的类实例
2015/04/02 PHP
PHP运用foreach神奇的转换数组(实例讲解)
2018/02/01 PHP
javascript脚本编程解决考试分数统计问题
2008/10/18 Javascript
js substr、substring和slice使用说明小记
2011/09/15 Javascript
Extjs中ComboBox加载并赋初值的实现方法
2012/03/22 Javascript
jQuery setTimeout()函数使用方法
2013/04/07 Javascript
javascript解析json数据的3种方式
2014/05/08 Javascript
绑定回车enter事件代码
2014/05/18 Javascript
javascript原型模式用法实例详解
2015/06/04 Javascript
微信小程序canvas写字板效果及实例
2017/06/15 Javascript
详解vue-cli + webpack 多页面实例配置优化方法
2017/07/13 Javascript
JavaScript实现简单的双色球(实例讲解)
2017/07/31 Javascript
vue实现长图垂直居上 vue实现短图垂直居中
2017/10/18 Javascript
原生JS生成指定位数的验证码
2020/10/28 Javascript
python 异常处理总结
2016/10/18 Python
Python守护线程用法实例
2017/06/23 Python
Python(TensorFlow框架)实现手写数字识别系统的方法
2018/05/29 Python
Python 变量类型详解
2018/10/10 Python
python ctypes库2_指定参数类型和返回类型详解
2019/11/19 Python
解析PyCharm Python运行权限问题
2020/01/08 Python
python把一个字符串切开的实例方法
2020/09/27 Python
python全栈开发语法总结
2020/11/22 Python
HTML5头部标签的一些常用信息小结
2016/10/23 HTML / CSS
德国百年厨具品牌WMF美国站:WMF美国
2016/09/12 全球购物
SmartBuyGlasses台湾:名牌眼镜,名牌太阳眼镜及隐形眼镜
2017/01/04 全球购物
为什么需要版本控制?
2013/08/08 面试题
先进班级集体事迹材料
2014/01/30 职场文书
外贸员简历中的自我评价
2014/03/04 职场文书
《大江保卫战》教学反思
2014/04/11 职场文书
大学生赌博检讨书
2014/09/22 职场文书
寻衅滋事罪辩护词
2015/05/21 职场文书
排查并解决MySQL生产库内存使用率高的报警
2022/04/11 MySQL
MySQL数据库事务的四大特性
2022/04/20 MySQL