Python 为什么uuuu enter uuuu引发异常时不执行uuuu exit uuuuuuuu

Python 为什么uuuu enter uuuu引发异常时不执行uuuu exit uuuuuuuu,python,contextmanager,Python,Contextmanager,我最近想知道当\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>引发异常时,没有隐式调用的原因是什么? 为什么它是这样设计的?我实现了一个ServiceRunner类,该类可以通过'with'关键字使用,结果证明,\uuuuuuuuuuuu从未被调用 例如: class ServiceRunner(object): def __init__(self, allocation_success): sel

我最近想知道当
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>引发异常时,没有隐式调用
的原因是什么?
为什么它是这样设计的?我实现了一个ServiceRunner类,该类可以通过
'with'
关键字使用,结果证明,
\uuuuuuuuuuuu
从未被调用

例如:

class ServiceRunner(object):
    def __init__(self, allocation_success):
        self.allocation_success = allocation_success

    def _allocate_resource(self):
        print("Service1 running...")
        print("Service2 running...")

        # running service3 fails ...
        if not self.allocation_success:
            raise RuntimeError("Service3 failed!")
        print("Service3 running...")

    def _free_resource(self):
        print("All services freed.")

    def __enter__(self):
        self._allocate_resource()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self._free_resource()
用法:

with ServiceRunner(allocation_success=True):
    pass

try:
    with ServiceRunner(allocation_success=False):
        pass
    except Exception as e:
        print(e)
输出:

Service1 running...
Service2 running...    
Service3 running...
All services freed.
Service1 running...
Service2 running...
Service3 running...
All services freed.
All services freed.

未调用函数
\uuuuu exit\uuuu
。服务1和服务2未被释放

我可以将
\u allocate\u resource()
移动到
\uuu init\uuu
,但在这种情况下,类不是很有用:

try:
    runner = ServiceRunner(allocation_success=True)
except Exception as e:
    print(e)
else:
    with runner as r:
        r.do()

    with runner as r:
        r.do()
输出:

Service1 running...
Service2 running...    
Service3 running...
All services freed.
Service1 running...
Service2 running...
Service3 running...
All services freed.
All services freed.
服务不会再次启动

我可以重新实现
\uuuu enter\uuuu
来处理异常,但它为函数添加了一些样板代码:

def __enter__(self):
    try:
        self._allocate_resource()
    except Exception as e:
        self.__exit__(*sys.exc_info())
        raise e

这是最好的解决方案吗?

如果您未能输入上下文,则没有理由尝试退出它,也就是说,如果您未能分配资源,则没有理由尝试释放它

IIUC,你要找的只是:

try:
   with ServiceRunner() as runner:
       runner.do()
except Exception as e:
    print(e)

为什么默认情况下会调用
\uuuuuuuuuuuuuuuuuuuuu
?如果我将open('file'u that'u not'u存在')作为infle:
,会发生什么?因为文件不存在,所以没有使用的资源被关闭。@roganjosh:那是另一种情况。如果该文件不存在,则永远不会调用
\uuu\uu enter\uu
。在引发异常之前,已分配了一些资源。我想确定他们被释放了。那么你在
\uuuu\uuu\uuu
上尝试/捕获的方法就可以了;不要觉得有义务使用
\uuuuu退出\uuuu