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

 更新时间:2018年02月09日 08:53:17   作者:苍松  
这篇文章主要介绍了Python with语句上下文管理器两种实现方法,结合实例形式较为详细的分析了Python上下文管理器的相关概念、功能、使用方法及相关操作注意事项,需要的朋友可以参考下

本文实例讲述了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的关键字监控及告警

    这篇文章主要为大家详细介绍了基于Python的关键字监控及告警,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • Python利用PySimpleGUI实现自制桌面翻译神器

    Python利用PySimpleGUI实现自制桌面翻译神器

    工作上经常需要与外国友人邮件沟通,奈何工作电脑没有安装有道词典一类的翻译软件,结合自己的需要,自己用PySimpleGUI撸一个桌面翻译神器,感兴趣的可以了解一下
    2022-09-09
  • python爬取微博评论的实例讲解

    python爬取微博评论的实例讲解

    在本篇文章里小编给大家整理的是一篇关于python爬取微博评论的实例讲解,有兴趣的朋友们可以学习下。
    2021-01-01
  • 使用Python的内建模块collections的教程

    使用Python的内建模块collections的教程

    这篇文章主要介绍了使用Python的内建模块collections的教程,示例代码基于Python2.x版本,需要的朋友可以参考下
    2015-04-04
  • 检测python爬虫时是否代理ip伪装成功的方法

    检测python爬虫时是否代理ip伪装成功的方法

    这篇文章主要介绍了检测python爬虫时是否代理ip伪装成功的方法以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。,需要的朋友可以参考下
    2019-07-07
  • python和go语言的区别是什么

    python和go语言的区别是什么

    在本篇文章中小编给大家整理的是一篇关于go语言和python的区别点,需要的朋友们可以学习下。
    2020-07-07
  • Python使用装饰器模拟用户登陆验证功能示例

    Python使用装饰器模拟用户登陆验证功能示例

    这篇文章主要介绍了Python使用装饰器模拟用户登陆验证功能,结合登录验证实例形式分析了装饰器的简单使用技巧,需要的朋友可以参考下
    2018-08-08
  • Python中re模块的常用方法总结

    Python中re模块的常用方法总结

    这篇文章主要给大家介绍了关于Python中re模块的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Flask使用SocketIO实现WebSocket与Vue进行实时推送

    Flask使用SocketIO实现WebSocket与Vue进行实时推送

    本文主要介绍了Flask使用SocketIO实现WebSocket与Vue进行实时推送,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • Python实现提取Word文档中的文本和图片

    Python实现提取Word文档中的文本和图片

    将内容从 Word 文档中提取出来可以方便我们对其进行其他操作,如将内容储存在数据库中,本文将介绍如何使用简单的代码实现从 Word 文档中提取文本和图片内容并保存,需要的可以参考下
    2023-12-12

最新评论