我想知道with
语句如何工作。我正在尝试转换以下内容:
with obj() as o:
do_something()
对此:
o = obj.__enter__()
try:
do_something()
except Exception as e:
obj.__exit__(type(e),e, **I don't know what should be here**)
else:
obj.__exit__(None, None , None)
那将会如何?如果我在任何地方都不对,请纠正我。我想知道要替换什么
**I don't know what should be here**
与。
答案 0 :(得分:3)
根据PEP-343,其中介绍了上下文管理器,代码
with obj() as o:
do_something()
等同于
mgr = obj()
exit = type(mgr).__exit__
value = type(mgr).__enter__(mgr)
exc = True
try:
try:
o = value
do_something()
except:
exc = False
if not exit(mgr, *sys.exc_info()):
raise
finally:
if exc:
exit(mgr, None, None, None)
一些注意事项:
o = type(mgr).__enter__(mgr)
,因为仅在o
没有引发异常的情况下才定义名称__enter__
,从而使我们完全可以输入try
语句。 (还有其他处理方法,但这就是我解释PEP-343的翻译的方式。)__exit__
可以在两个不同的地方调用。如果我们捕获到异常,则会将有关该异常的信息传递给__exit__
,这将阻止调用代码返回True
时看到该异常。finally
块可确保__exit__
恰好被调用一次。也就是说,如果没有引发异常,我们要调用它,但是如果第一个调用通过返回True
或引发异常本身吞下了异常,则不要再次调用它。答案 1 :(得分:1)
如果只是作为学习实验,这很好。我认为实际上不应该使用它。通常,您不需要直接调用Python的magic方法。
您真的想在__exit__
块中调用finally
。您可以通过调用__exit__
获得要提供给sys.exc_info
的三个参数。
import sys
o = obj.__enter__()
try:
do_something()
finally:
obj.__exit__(*sys.exc_info())