Python 基础教程

Python 高级教程

Python 相关应用

Python 笔记

Python with 关键字

Python 关键字 Python 关键字


with语句是从Python 2.5开始引入的一种与异常处理相关的功能(2.5版本中要通过“from __future__ import with_statement”导入后才可以使用),从2.6版本开始缺省可用。with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。

with 语句的语法格式如下:

with context_expression [as target(s)]:
    withbody

这里context_expression要返回一个上下文管理器对象,该对象并不是赋值给as子句中的target(s) ,而是如果指定了as子句的话,会将上下文管理器的__enter__()方法的返回值赋值给target(s)。

target(s)可以是单个变量,或者由“()”括起来的元组(不能是仅仅由“,”分隔的变量列表,必须加“()”)。

要使用with语句,首先要明白上下文管理器这一概念。有了上下文管理器,with语句才能工作。

  • 上下文管理协议(Context Management Protocol):包含方法__enter__()和__exit__(),支持该协议的对象要实现这两个方法。
  • 上下文管理器(Context Manager):支持上下文管理协议的对象,这种对象实现了__enter__()和__exit__()方法。上下文管理器定义执行with语句时要建立的运行时上下文,负责执行with语句块上下文中的进入与退出操作。通常使用with语句调用上下文管理器,也可以通过直接调用其方法来使用。
  • 运行时上下文(runtime context):由上下文管理器创建,通过上下文管理器的__enter__()和__exit__()方法实现,__enter__()方法在语句体执行之前进入运行时上下文,__exit__()在语句体执行完后从运行时上下文退出。with语句支持运行时上下文这一概念。
  • 上下文表达式(Context Expression):with语句中跟在关键字with之后的表达式,该表达式要返回一个上下文管理器对象。
  • 语句体(with-body):with语句包裹起来的代码块,在执行语句体之前会调用上下文管理器的__enter__()方法,执行完语句体之后会执行__exit__()方法。

with语句的执行原理如下:

  1. 执行context_expression,生成上下文管理器context_manager。
  2. 调用上下文管理器的__enter__()方法;如果使用了as子句,则将__enter__()方法的返回值赋值给as子句中的target(s)。
  3. 执行语句体with-body。
  4. 不管是否执行过程中是否发生了异常,执行上下文管理器的__exit__()方法,__exit__()方法负责执行“清理”工作,如释放资源等。如果执行过程中没有出现异常,或者语句体中执行了语句break/continue/return,则以None作为参数调用__exit__(None, None, None) ;如果执行过程中出现异常,则使用sys.exc_info得到的异常信息为参数调用__exit__(exc_type, exc_value, exc_traceback) 。
  5. 出现异常时,如果__exit__(type, value, traceback) 返回False,则会重新抛出异常,让with之外的语句逻辑来处理异常,这也是通用做法;如果返回 True,则忽略异常,不再对异常进行处理。

示例如下:

class A:
    def __enter__(self):
        print('in enter')

    def __exit__(self, e_t, e_v, t_b):
        print('in exit')


with A() as a:
    print('in with')

输出结果为:

in enter
in with
in exit