深挖python上下文管理——類的__init__、__enter__、__exit__、__del__在with下的表現

場景:今天因爲需要測試一個服務,在測試前,需要把它依賴的服務幹掉,在測試完成後(不論報錯),再把服務起來。
因爲它是其中的一個步驟,其他時間服務需開啓,不適用unittest通用的setup和teardown
所以想到寫一個類,通過上下文來管理服務狀態。

這是第一段測試代碼

# coding: utf-8
class C:
    def __init__(self):
        print("init")

    def __enter__(self):
        print("enter")

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("exit")

    def __del__(self):
        print("del")


if __name__ == '__main__':
    a = C()
    print("st")
    with a:
        print("hi")
    with a:
        print("hi")
    print("ed")

發現輸出是這樣的

init
st
enter
hi
exit
enter
hi
exit
ed
del

說明with一個已經存在的實例,會在起代碼塊開始和結束時執行實例的__enter__和__exit__,且可以執行多次

而如果修改源碼,變成如下這樣

...

if __name__ == '__main__':
    print("st")
    with C():
        print("hi")
    with C():
        print("hi")
    print("ed")

發現輸出將是這樣的

st
init
enter
hi
exit
del
init
enter
hi
exit
del
ed

說明在with語句裏實例化類時,類的生命週期就只有with這一部分,所以會打印init和del兩次,而enter和exit仍然有效,該實例在with語句結束後該類就被刪除析構

靈活的選擇with一個類/實例,合理安排init del和enter exit的方法,可以針對需要的場景做定製的上下文管理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章