gpt4 book ai didi

python - 为什么在 __enter__ 引发异常时不执行 __exit__

转载 作者:行者123 更新时间:2023-12-05 03:58:59 25 4
gpt4 key购买 nike

我最近想知道当 __enter__ 引发异常时不隐式调用 __exit__ 的原因是什么?为什么要这样设计?我正在实现服务运行器类以供 'with' 关键字使用,结果 __exit__ 从未被调用。

例子:

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 failed!

函数 __exit__ 没有被调用。 Service1 和 Service2 没有被释放。

我可以将 _allocate_resource() 移动到 __init__ 但是类在这种用法中不是很有用:

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.
All services freed.

服务没有重新启动。

我可以重新实现 __enter__ 来处理异常,但它会向函数添加一些样板代码:

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)

关于python - 为什么在 __enter__ 引发异常时不执行 __exit__,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57524533/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com