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