with 语句的等效 try 语句是什么?
What is the equivalent try statement of the with statement?
在阅读了 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)
编辑
正确的等效 Python 代码(真正的 CPython 实现在 C 中)实际上是由 Guido van Rossum 自己在 PEP 343:
中给出的
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
子句,以处理存在非本地 goto 语句(break
、continue
、return
) 在 suite
.
但是我不明白为什么 PEP 343 中的等效 Python 代码将 finally
子句放在外部 try
语句而不是内部try
声明?
Nick Coghlan,PEP 343, answered on the Python bug tracker 的另一位作者:
It's a matter of historical timing: PEP 343 was written before
try/except/finally was allowed, when try/finally and try/except were
still distinct statements.
However, PEP 341 was also accepted and implemented for Python 2.5,
allowing for the modern try/except/finally form:
https://docs.python.org/dev/whatsnew/2.5.html#pep-341-unified-try-except-finally
因此 with
语句的现代 try
语句等效 Python 代码是:
manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False
try:
TARGET = value # only if `as TARGET` is present in the with statement
SUITE
except:
import sys
hit_except = True
if not exit(manager, *sys.exc_info()):
raise
finally:
if not hit_except:
exit(manager, None, None, None)
在阅读了 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)
编辑
正确的等效 Python 代码(真正的 CPython 实现在 C 中)实际上是由 Guido van Rossum 自己在 PEP 343:
中给出的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
子句,以处理存在非本地 goto 语句(break
、continue
、return
) 在suite
.
但是我不明白为什么 PEP 343 中的等效 Python 代码将 finally
子句放在外部 try
语句而不是内部try
声明?
Nick Coghlan,PEP 343, answered on the Python bug tracker 的另一位作者:
It's a matter of historical timing: PEP 343 was written before try/except/finally was allowed, when try/finally and try/except were still distinct statements.
However, PEP 341 was also accepted and implemented for Python 2.5, allowing for the modern try/except/finally form: https://docs.python.org/dev/whatsnew/2.5.html#pep-341-unified-try-except-finally
因此 with
语句的现代 try
语句等效 Python 代码是:
manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False
try:
TARGET = value # only if `as TARGET` is present in the with statement
SUITE
except:
import sys
hit_except = True
if not exit(manager, *sys.exc_info()):
raise
finally:
if not hit_except:
exit(manager, None, None, None)