码迷,mamicode.com
首页 > 编程语言 > 详细

python中的上下文管理器

时间:2018-12-23 23:57:40      阅读:323      评论:0      收藏:0      [点我收藏+]

标签:int   计算   文件   extman   链接   实例   管理   异常   manager   

上下文管理器是装饰器的亲戚,是try..except..finally的替代手段

凡是try语句能做的事都可以用上下文管理器实现

主要应用场景 确保资源的释放 如打开的文件 数据库链接

另外,如果代码中出现大量try语句 重复 可以用上下文管理器优化代码


上下文管理器的实现

class ContextManager(object):
    def __init__(self):
        pass
    def __enter__(self):
        pass
    def __exit__(self, exc_type, exc_val, exc_tb)
        pass

核心方法 __enter__和 __exit__

实例化ContextManager时 enter方法会被调用

with ContextManager():
    pass

这里with代码段执行结束后 exit方法会被调用

__exit__方法的参数:

  1. exc_type 异常的类型
  2. exc_val 异常的值
  3. exc_tb 异常的回溯 tranceback

当with代码段中出现异常时,exit方法被调用,并将异常参数传入

可以在exit中对异常进行处理

__exit__方法的返回值:

  • True 不抛出异常 假装自己已经处理了
  • False 将异常抛出

上下文管理器的例子

with open("./canglaoshi.rmvb", ‘rb‘) as f:
    f.read(1024)
    .....    

这里就用到的上下文管理器,with + 表达式 开始使用上下文管理器,

这里的open()是一个表达式,表达式计算出的值不会这这里赋给任何变量

这里f的值是enter方法的返回值,当然enter方法可以返回表达式的计算结果


上下文管理器的另一种实现方式

使用生成器函数加contextmanager装饰器可以更简单的实现上下文管理器

from contextlib import contextmanager

@contextmanager
def my_file_open(path, mode):
    f = open(path, mode)
    yield f
    f.close()
    
with my_file_open(‘./xx.txt‘, ‘a+‘) as f:
    f.read()
    ...    

yield将函数分为两部分,第一部分相当于__enter__()方法

yield f 相当于enter方法返回f

第二部分相当与exit方法,可以进行资源释放

这种方式虽然简单,但是当with代码段中有异常发生时,需要使用try来处理,否则yield之后的代码不会执行

from contextlib import contextmanager


@contextmanager
def test():
    print("enter method")
    var = "hello"
    try:
        yield var
    except Exception as e:
        print(e)
    print("exit method")


with test() as var:
    print(var)
    print(1 + 1)
    print(2 / 0)

python中的上下文管理器

标签:int   计算   文件   extman   链接   实例   管理   异常   manager   

原文地址:https://www.cnblogs.com/endurance9/p/10165848.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!