【发布时间】:2019-12-13 12:26:22
【问题描述】:
在阅读了Python语言文档的with statement section之后,我想知道是否声明这段Python代码是正确的:
with EXPRESSION as TARGET:
SUITE
相当于这个:
try:
manager = (EXPRESSION)
value = manager.__enter__()
TARGET = value # only if `as TARGET` is present in the with statement
SUITE
except:
import sys
if not manager.__exit__(*sys.exc_info()):
raise
else:
manager.__exit__(None, None, None)
编辑
Guido van Rossum 本人在PEP 343 中实际上给出了正确的等效 Python 代码(真正的 CPython 实现在 C 中):
mgr = (EXPR)
exit = type(mgr).__exit__ # Not calling it yet
value = type(mgr).__enter__(mgr)
exc = True
try:
try:
VAR = value # Only if "as VAR" is present
BLOCK
except:
# The exceptional case is handled here
exc = False
if not exit(mgr, *sys.exc_info()):
raise
# The exception is swallowed if exit() returns true
finally:
# The normal and non-local-goto cases are handled here
if exc:
exit(mgr, None, None, None)
自 Python 3.6 以来,这发生了一些变化:现在 __enter__ 函数在__exit__ 函数之前加载(参见https://bugs.python.org/issue27100)。
所以我的等效 Python 代码存在三个缺陷:
- 应在调用
__enter__函数之前加载__enter__和__exit__函数。 -
__enter__函数应在try语句之外调用(参见语言文档中第 4 点的注释)。 -
else子句应改为finally子句,以处理suite中存在非本地goto 语句(break、continue、return)的情况。李>
但是我不明白为什么 PEP 343 中的等效 Python 代码将 finally 子句放在外部 try 语句而不是内部 try 语句中?
【问题讨论】:
-
不,上下文关闭总是会发生,不仅仅是在异常的情况下。因此,我认为这些结构之间没有明显的重叠。
-
您链接到明确提及
finally的文档,它们目前不等价,因为除非出现错误,否则不会执行退出 -
@guidot 很好,我忘了包括没有例外的情况。让我更新一下问题。
-
尽可能简单地说,
with与try\except\finally相似,但与try\except不同。
标签: python try-catch with-statement