深挖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的方法,可以针对需要的场景做定制的上下文管理

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