zoukankan      html  css  js  c++  java
  • 实现文件上下文管理(__enter__和__exit__)

    • 我们知道在操作文件对象的时候可以这么写
    with open('a.txt') as f:
        '代码块'
    
    • 上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法

    一、上下文管理协议

    class Open:
        def __init__(self, name):
            self.name = name
    
        def __enter__(self):
            print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
            # return self
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('with中代码块执行完毕时执行我啊')
    
    
    with Open('a.txt') as f:
        print('=====>执行代码块')
        # print(f,f.name)
    
    出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
    =====>执行代码块
    with中代码块执行完毕时执行我啊
    
    • __exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行
    class Open:
        def __init__(self, name):
            self.name = name
    
        def __enter__(self):
            print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('with中代码块执行完毕时执行我啊')
            print(exc_type)
            print(exc_val)
            print(exc_tb)
    
    
    try:
        with Open('a.txt') as f:
            print('=====>执行代码块')
            raise AttributeError('***着火啦,救火啊***')
    except Exception as e:
        print(e)
    
    出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
    =====>执行代码块
    with中代码块执行完毕时执行我啊
    <class 'AttributeError'>
    ***着火啦,救火啊***
    <traceback object at 0x1065f1f88>
    ***着火啦,救火啊***
    
    • 如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
    class Open:
        def __init__(self, name):
            self.name = name
    
        def __enter__(self):
            print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('with中代码块执行完毕时执行我啊')
            print(exc_type)
            print(exc_val)
            print(exc_tb)
            return True
    
    
    with Open('a.txt') as f:
        print('=====>执行代码块')
        raise AttributeError('***着火啦,救火啊***')
    print('0' * 100)  #------------------------------->会执行
    
    出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
    =====>执行代码块
    with中代码块执行完毕时执行我啊
    <class 'AttributeError'>
    ***着火啦,救火啊***
    <traceback object at 0x1062ab048>
    0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    

    二、模拟open

    113-enter,exit-open.jpg?x-oss-process=style/watermark

    class Open:
        def __init__(self, filepath, mode='r', encoding='utf-8'):
            self.filepath = filepath
            self.mode = mode
            self.encoding = encoding
    
        def __enter__(self):
            # print('enter')
            self.f = open(self.filepath, mode=self.mode, encoding=self.encoding)
            return self.f
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            # print('exit')
            self.f.close()
            return True
    
        def __getattr__(self, item):
            return getattr(self.f, item)
    
    
    with Open('a.txt', 'w') as f:
        print(f)
        f.write('aaaaaa')
        f.wasdf  #抛出异常,交给__exit__处理
    
    <_io.TextIOWrapper name='a.txt' mode='w' encoding='utf-8'>
    

    三、优点

    1. 使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预

    2. 在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处

  • 相关阅读:
    destoon-手机版商铺中视频打开提示请登录查看,登录之后还是提示
    destoon-开启远程ftp后会员头像上传不显示
    destoon-手机版会员公司主页首页调用商城信息
    destoon-列表页调用分类属性
    destoon-供应列表调用分类属性值
    destoon会员公司主页扫描二维码手机上显示空白
    destoon-7.0资讯开启内容显示上一篇下一篇不显示
    destoon-使用手机号注册会员名提示“会员登录名已经被注册”的限制去掉
    destoon配置微信提示48001
    destoon-7.0手机版腾讯视频不显示
  • 原文地址:https://www.cnblogs.com/nickchen121/p/10991541.html
Copyright © 2011-2022 走看看