8.5. with
语句
with
语句用于包装带有使用上下文管理器 (参见 with 语句上下文管理器 一节) 定义的方法的代码块的执行。 这允许对普通的 try
…except
…finally
使用模式进行封装以方便地重用。
- with_stmt ::= "with"
with_item
(","with_item
)* ":"suite
- with_item ::=
expression
["as"target
]
带有一个“项目”的 with
语句的执行过程如下:
对上下文表达式 (在
with_item
中给出的表达式) 求值以获得一个上下文管理器。载入上下文管理器的
__enter__()
以便后续使用。载入上下文管理器的
__exit__()
以便后续使用。发起调用上下文管理器的
__enter__()
方法。如果
with
语句中包含一个目标,来自__enter__()
的返回值将被赋值给它。注解
with
语句会保证如果__enter__()
方法返回时未发生错误,则__exit__()
将总是被调用。 因此,如果在对目标列表赋值期间发生错误,则会将其视为在语句体内部发生的错误。 参见下面的第 6 步。执行语句体。
发起调用上下文管理器的
__exit__()
方法。 如果语句体的退出是由异常导致的,则其类型、值和回溯信息将被作为参数传递给__exit__()
。 否则的话,将提供三个None
参数。如果语句体的退出是由异常导致的,并且来自
__exit__()
方法的返回值为假,则该异常会被重新引发。 如果返回值为真,则该异常会被抑制,并会继续执行with
语句之后的语句。如果语句体由于异常以外的任何原因退出,则来自
__exit__()
的返回值会被忽略,并会在该类退出正常的发生位置继续执行。
以下代码:
with EXPRESSION as TARGET:
SUITE
在语义上等价于:
manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False
try:
TARGET = value
SUITE
except:
hit_except = True
if not exit(manager, *sys.exc_info()):
raise
finally:
if not hit_except:
exit(manager, None, None, None)
如果有多个项目,则会视作存在多个 with
语句嵌套来处理多个上下文管理器:
with A() as a, B() as b:
SUITE
在语义上等价于:
with A() as a:
with B() as b:
SUITE
在 3.1 版更改: 支持多个上下文表达式。
参见
PEP 343 - “with” 语句
Python with
语句的规范描述、背景和示例。