zoukankan      html  css  js  c++  java
  • 实现文件上下文管理(\_\_enter\_\_和\_\_exit\_\_)

    实现文件上下文管理(__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,11)
            print(exc_val,22)
            print(exc_tb,33)
    
    
    try:
        with Open('a.txt') as f:
            print('=====>执行代码块')
            raise AttributeError('***着火啦,救火啊***,11')
    except Exception as e:
        print(e)
    
    
    出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
    =====>执行代码块
    with中代码块执行完毕时执行我啊
    <class 'AttributeError'> 11
    ***着火啦,救火啊***,11 22
    <traceback object at 0x0BBB3BE8> 33
    ***着火啦,救火啊***,11
    

    异常都会被执行

    • 如果__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, 1)
            print(exc_val, 2)
            print(exc_tb, 3)
            return True
    
    
    with Open('a.txt') as f:
        print('=====>执行代码块')
        raise AttributeError('***着火啦,救火啊***')
    
    
    出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
    =====>执行代码块
    with中代码块执行完毕时执行我啊
    <class 'AttributeError'> 1
    ***着火啦,救火啊*** 2
    <traceback object at 0x0BD63BE8> 3
    

    二、模拟open

    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()
            print(exc_type, 1)
            print(exc_val, 2)
            print(exc_tb, 3)
            # 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'>
    
    <class 'AttributeError'> 1
    '_io.TextIOWrapper' object has no attribute 'wasdf' 2
    <traceback object at 0x0C443BE8> 3
    
    

    三、优点

    1. 使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
    2. 在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处
  • 相关阅读:
    Dybala我错了%Dybala
    2019.7.22考试反思
    2019.7.19考试反思
    2019.7.18 考试反思
    数论总结之 乘法逆元
    数论总结之 卢卡斯定理
    游记 Day2
    【BSGS】Discrete Logging
    【卡特兰数】树屋阶梯
    【链接】 一篇很好的有关prufer序列的博文
  • 原文地址:https://www.cnblogs.com/randysun/p/12253031.html
Copyright © 2011-2022 走看看