Python中with语句||上下文管理器结构及用法

  • 上下文管理器

顾名思义,上下文管理器就是管理上下文的。实现代码块执行前准备,代码快执行后收拾。

应用场景:管理各种系统资源(文件、锁定、连接)时,如果出现异常比较棘手。异常会导致控制流跳过负责释放关键资源的语句。比如打开一个文件进行操作时发生意外(磁盘已满、特殊终端信号让其终止…),可能导致文件关闭操作无法执行,进而耗费系统资源。

之前采用try/finally语句来解决此类问题,Python2.5之后加入上下文管理器处理此问题,增强代码可读性、减少错误。

  • with语句

with语句用于执行上下文操作,基本语法:

with context_expr [as var]:
	with_suit

with语句只能工作于支持上下文管理协议(context management protocol)的对象。也就是说只有内建了”上下文管理”的对象才能和 with 一起工作。

Python内置了一些支持该协议的对象,如下所列是一个简短列表:

  • file
  • decimal.Context
  • thread.LockType
  • threading.Lock
  • threading.RLock
  • threading.Condition
  • threading.Semaphore
  • threading.BoundedSemaphore

file举例:

with open('pickle_symbols.pickle', 'rb') as f:   # 打开文件,如果一切正常,读取数据赋值给df,之后关闭文件
    df = pickle.load(f)
print(df)

无论是在这一段代码的开始,中间,还是结束时发生异常,会执行清理的代码,此 外文件仍会被自动的关闭。

  • 自定义上下文管理器

前面提到with语句只能工作于支持上下文管理协议的对象,如果默认对象不能满足功能,就需要自己定义。核心就是下面两个方法:

__enter__():在使用with语句时调用,会话管理器在代码块开始前调用,返回值与as后的参数绑定

__exit__():会话管理器在代码块执行完成好后调用,在with语句完成时,对象销毁之前调用

with语句的执行流程

1. 执行 context_exp 以获取上下文管理器
2. 加载上下文管理器的 __exit__() 方法以备稍后调用
3. 调用上下文管理器的 __enter__() 方法
4. 如果有 as var 从句,则将 __enter__() 方法的返回值赋给 var
5. 执行子代码块 with_suit
6. 调用上下文管理器的 __exit__() 方法,如果 with_suit 的退出是由异常引发的,那么该异常的 type、value 和 traceback 会作为参数传给 __exit__(),否则传三个 None
7. 如果 with_suit 的退出由异常引发,并且 __exit__() 的返回值等于 False,那么这个异常将被重新引发一次;如果 __exit__() 的返回值等于 True,那么这个异常就被无视掉,继续执行后面的代码
  • contextlib模块

contextlib模块可以提供更方便的上下午管理器。

  • Reference

  1. Object becomes None when using a context manager
  2. PEP 343 – The “with” Statement
  3. Understanding Python’s “with” statement
  4. The with command and custom classes
  5. Python with解析 __enter__()、__exit__() (十五)
  6. 浅谈 Python 的 with 语句
  7. Object becomes None when using a context manager
  8. Python深入02 上下文管理器
  9. 旷世的忧伤
  10. python __enter____exit__的作用,以及与 with 语句的关系

猜你喜欢

转载自blog.csdn.net/The_Time_Runner/article/details/89683452
今日推荐