Python with语句上下文管理器两种实现方法分析


Posted in Python onFebruary 09, 2018

本文实例讲述了Python with语句上下文管理器。分享给大家供大家参考,具体如下:

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

对于这种情况python提供了上下文管理器(Context Manager)的概念,可以通过上下文管理器来定义/控制代码块执行前的准备动作,以及执行后的收尾动作。

一、为何使用上下文管理器

1、不使用上下文管理器的情况

通过try...finally语句执行异常处理和关闭句柄的动作。

logger = open("log.txt", "w")
try:
logger.write('Hello ')

logger.write('World')
finally:

logger.close()
print logger.closed

2、使用上下文管理器

默认文件Python的内置file类型是支持上下文管理协议的。
使用上下文管理器with使得依据精简了很多。

with open("log.txt", "w") as logger:
logger.write('Hello ')

logger.write('World')
print logger.closed

二、实现上下文管理器实现上下文管理器有两种方式实现。方法一:类实现__enter__和__exit__方法。方法二:contextlib模块装饰器和生成器实现。

下面我们通过两种方法分别实现一个自定义的上下文管理器。

1、方法一:通过类实现__enter__和__exit__方法

class File(object):
 def __init__(self, file_name, method):
  self.file_obj = open(file_name, method)
 def __enter__(self):
  return self.file_obj
 def __exit__(self, type, value, traceback):
  self.file_obj.close()
with File('demo.txt', 'w') as opened_file:
 opened_file.write('Hola!')

实现__enter__和__exit__方法后,就能通过with语句进行上下文管理。

a、底层都发生了什么?

1、with语句先暂存了File类的__exit__方法,然后它调用File类的__enter__方法。
2、__enter__方法打开文件并返回给with语句,打开的文件句柄被传递给opened_file参数。
3、with语句调用之前暂存的__exit__方法,__exit__方法关闭了文件。

b、异常处理

关于异常处理,with语句会采取哪些步骤。

1. 它把异常的type,value和traceback传递给__exit__方法
2. 它让__exit__方法来处理异常
3. 如果__exit__返回的是True,那么这个异常就被忽略。
4. 如果__exit__返回的是True以外的任何东西,那么这个异常将被with语句抛出。

异常抛出

#异常抛出,_exit__返回的是True以外的任何东西,那么这个异常将被with语句抛出
class File(object):
 def __init__(self, file_name, method):
  self.file_obj = open(file_name, method)
 def __enter__(self):
  return self.file_obj
 def __exit__(self, type, value, traceback):
  self.file_obj.close()
  print "type:",type
  print "value:",value
  print "traceback:",traceback
with File('demo.txt', 'w') as opened_file:
 opened_file.undefined_function('Hola!')
#output================================================
# type: <type 'exceptions.AttributeError'>
# value: 'file' object has no attribute 'undefined_function'
# traceback: <traceback object at 0x000000000262D9C8>
#  opened_file.undefined_function('Hola!')
# AttributeError: 'file' object has no attribute 'undefined_function'

异常忽略:

#异常忽略,__exit__返回的是True,那么这个异常就被忽略。
class File(object):
 def __init__(self, file_name, method):
  self.file_obj = open(file_name, method)
 def __enter__(self):
  return self.file_obj
 def __exit__(self, exception_type, exception_value, traceback):
  print("Exception has been handled")
  self.file_obj.close()
  return True
with File('demo.txt', 'w') as opened_file:
 opened_file.undefined_function('Hola!')
# output==================================
# Exception has been handled

2、方法二:contextlib模块装饰器和生成器实现

这种方式实现更优雅,我个人更喜欢这种方式。

yield之前的代码由__enter__方法执行,yield之后的代码由__exit__方法执行。本质上还是__enter____exit__方法。

# coding:utf-8
import contextlib
@contextlib.contextmanager
def myopen(filename, mode):
 f = open(filename, mode)
 try:
  yield f.readlines()
 except Exception as e:
  print e
 finally:
  f.close()
if __name__ == '__main__':
 with myopen(r'c:\ip2.txt', 'r') as f:
  for line in f:
   print line

3、with语句上多个下文关联

直接通过一个with语句打开多个上下文,即可同时使用多个上下文变量,而不必需嵌套使用with语句。

class File(object):
 def __init__(self, file_name, method):
  self.file_obj = open(file_name, method)
 def __enter__(self):
  return self.file_obj
 def __exit__(self, exception_type, exception_value, traceback):
  self.file_obj.close()
  return True
with File('demo.txt', 'w') as f1,File('demo.txt','w') as f2:
 print f1,f2
# Output============================# <open file 'demo.txt', mode 'w' at 0x000000000263D150> <open file 'demo.txt', mode 'w' at 0x000000000263D1E0>

更多关于Python相关内容可查看本站专题:《Python数据结构与算法教程》、《Python Socket编程技巧总结》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》及《Python入门与进阶经典教程》

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
python自动化测试之从命令行运行测试用例with verbosity
Sep 28 Python
python压缩文件夹内所有文件为zip文件的方法
Jun 20 Python
Django框架中数据的连锁查询和限制返回数据的方法
Jul 17 Python
Python简单实现的代理服务器端口映射功能示例
Apr 08 Python
Python Pandas找到缺失值的位置方法
Apr 12 Python
python代码实现逻辑回归logistic原理
Aug 07 Python
用Python爬取QQ音乐评论并制成词云图的实例
Aug 24 Python
pytorch下使用LSTM神经网络写诗实例
Jan 14 Python
Python使用进程Process模块管理资源
Mar 05 Python
Python3实现个位数字和十位数字对调, 其乘积不变
May 03 Python
教你如何使用Python下载B站视频的详细教程
Apr 29 Python
使用python+pygame开发消消乐游戏附完整源码
Jun 10 Python
Python遍历pandas数据方法总结
Feb 09 #Python
python中的闭包函数
Feb 09 #Python
基于Python socket的端口扫描程序实例代码
Feb 09 #Python
利用python 更新ssh 远程代码 操作远程服务器的实现代码
Feb 08 #Python
Tensorflow 利用tf.contrib.learn建立输入函数的方法
Feb 08 #Python
django数据库migrate失败的解决方法解析
Feb 08 #Python
python使用锁访问共享变量实例解析
Feb 08 #Python
You might like
php编写的简单页面跳转功能实现代码
2013/11/27 PHP
php下载文件,添加响应头的简单实例
2016/09/22 PHP
setInterval 和 setTimeout会产生内存溢出
2008/02/15 Javascript
javascript indexOf函数使用说明
2008/07/03 Javascript
JavaScript 笔记二 Array和Date对象方法
2010/05/22 Javascript
js下通过getList函数实现分页效果的代码
2010/09/17 Javascript
jQuery的12招常用技巧分享
2011/08/08 Javascript
iframe异步加载实现点击左边菜单加载右边内容实例讲解
2013/03/04 Javascript
jquery时间下拉框小例子
2013/04/15 Javascript
js原型继承的两种方法对比介绍
2014/03/30 Javascript
javascript中的throttle和debounce浅析
2014/06/06 Javascript
JavaScript实现设计模式中的单例模式的一些技巧总结
2016/05/17 Javascript
VUEJS实战之构建基础并渲染出列表(1)
2016/06/13 Javascript
20分钟打造属于你的Bootstrap站点
2016/07/27 Javascript
bootstrap3 dialog 更强大、更灵活的模态框
2017/04/20 Javascript
JavaScript标准对象_动力节点Java学院整理
2017/06/27 Javascript
vue+axios新手实践实现登陆的示例代码
2018/06/06 Javascript
bootstrap 路径导航 分页 进度条的实例代码
2018/08/06 Javascript
10个最受欢迎的 JavaScript框架(推荐)
2019/04/24 Javascript
angularjs1.X 重构controller 的方法小结
2019/08/15 Javascript
layui form.render('select', 'test2') 更新渲染的方法
2019/09/27 Javascript
Vue 设置axios请求格式为form-data的操作步骤
2019/10/29 Javascript
VUE中V-IF条件判断改变元素的样式操作
2020/08/09 Javascript
Python全排列操作实例分析
2018/07/24 Python
django 外键model的互相读取方法
2018/12/15 Python
pytorch下大型数据集(大型图片)的导入方式
2020/01/08 Python
Python xlrd excel文件操作代码实例
2020/03/10 Python
python+adb命令实现自动刷视频脚本案例
2020/04/23 Python
英国运动风奢侈品购物网站:Maison De Fashion
2020/08/28 全球购物
优秀英语专业毕业生求职信
2013/11/23 职场文书
教师年度考核自我鉴定
2014/01/19 职场文书
销售行政专员岗位职责
2014/06/10 职场文书
亲戚关系证明
2015/06/24 职场文书
如何写通讯稿
2015/07/22 职场文书
战友聚会致辞
2015/07/28 职场文书
Python机器学习之基于Pytorch实现猫狗分类
2021/06/08 Python