實現文件上下文管理(__enter__和__exit__)

  • 咱們知道在操做文件對象的時候能夠這麼寫
with open('a.txt') as f:
    '代碼塊'
  • 上述叫作上下文管理協議,即with語句,爲了讓一個對象兼容with語句,必須在這個對象的類中聲明__enter__和__exit__方法

1、上下文管理協議

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

2、模擬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'>

3、優勢

  1. 使用with語句的目的就是把代碼塊放入with中執行,with結束後,自動完成清理工做,無須手動干預編程

  2. 在須要管理一些資源好比文件,網絡鏈接和鎖的編程環境中,能夠在__exit__中定製自動釋放資源的機制,你無須再去關係這個問題,這將大有用處網絡

相關文章
相關標籤/搜索