将“with”语句转换为“try”语句

2024-04-19 23:29:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我想知道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**与。你知道吗


Tags: noneobjhereaswithexit语句be
2条回答

如果只是作为一个学习实验,这是好的。我不认为它实际上不应该被使用。通常不需要直接调用Python的magic方法。你知道吗

确实要在finally块中调用__exit__。要提供给__exit__的三个参数可以通过调用sys.exc_info获得。你知道吗

import sys

o = obj.__enter__()
try:
    do_something()
finally:
    obj.__exit__(*sys.exc_info())

根据引入了上下文管理器的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)

注意事项:

  1. 我们不写o = type(mgr).__enter__(mgr),因为只有在__enter__没有引发异常时才定义名称o,这样我们就可以输入try语句。(有其他的方法来处理这个问题,但这就是我如何解释PEP-343的翻译。)
  2. __exit__可以在两个不同的地方调用。如果捕获到异常,我们会将有关该异常的信息传递给__exit__,这样可以防止调用代码在返回True时看到它。你知道吗
  3. finally块确保__exit__只被调用一次。也就是说,如果没有引发异常,我们希望调用它,但是如果第一个调用通过返回True吞并了一个异常或者引发了一个异常本身,我们就不想再次调用它。你知道吗

相关问题 更多 >