Python with、__enter__()、__exit__()用法

with语法格式:

with EXPR as Variable:

    BLOCK


语法解释:

  • EXPR可以是任意表达式;

  • as Variable是可选的

  • as的作用类似于=赋值。


一般的执行过程是这样的:

  • 执行EXPR,生成上下文管理器context_manager;

  • 获取上下文管理器的__exit()__方法,并保存起来用于之后的调用;

  • 调用上下文管理器的__enter__()方法;

  • 如果使用了as子句,则将__enter__()方法的返回值赋值给as子句中的 Variable;

  • 执行 BLOCK 中的代码块;

  • 最后调用__exit__退出代码

# with 的工作流程
class Sample:
    def __enter__(self):
        print("In __enter__()")
        return "Foo"

    def __exit__(self, type, value, trace):
        print("In __exit__()")

def get_sample():
    return Sample()

with get_sample() as sample: # __enter__() 返回的值赋值给 as 后的变量 sample
    print("sample:", sample) # 此时sample 为 __enter__()的返回值

"""
输出:
In __enter__()
sample: Foo
In __exit__()
"""

 

with真正强大之处是它可以处理异常:

  • __exit__方法有三个参数val,type 和 trace,在with后面的代码块抛出任何异常时,__exit__()方法被执行。

  • 异常抛出时,与之关联的type,value和stack trace传给__exit__()方法,可以通过trace打印抛出的异常。

  • 开发库时,清理资源,关闭文件等等操作,都可以放在__exit__方法当中。

# with真正强大之处是它可以处理异常
class Sample:
    def __enter__(self):
        return self

    def __exit__(self, type, value, trace):
        print("type:", type)
        print("value:", value)
        print("trace:", trace)

    def do_something(self):
        bar = 1/0
        return bar + 10

with Sample() as sample:
    sample.do_something()

"""
输出:
type: <class 'ZeroDivisionError'>
value: division by zero
trace: <traceback object at 0x7f9f2b33e680>

发生异常: ZeroDivisionError
division by zero
  File "/Users/Shared/script/practice/Untitled-1.py", line 34, in do_something
    bar = 1/0
  File "/Users/Shared/script/practice/Untitled-1.py", line 38, in <module>
    sample.do_something()
"""

 

posted @ 2022-11-04 20:40  yudai  阅读(318)  评论(0编辑  收藏  举报