Tho*_*ner 16 python exception-handling contextmanager
我想我已经读过内部异常,with
不允许__exit__
正确调用.如果我在这个笔记上错了,请原谅我的无知.
所以我在这里有一些伪代码,我的目标是使用锁定上下文,在__enter__
记录开始日期时间并返回锁定ID,并在__exit__
记录结束日期时间并释放锁定:
def main():
raise Exception
with cron.lock() as lockid:
print('Got lock: %i' % lockid)
main()
Run Code Online (Sandbox Code Playgroud)
除了安全地存在上下文之外,我怎么还能引发错误?
注意:我故意在此伪代码中引发基本异常,因为我想在任何异常时安全退出,而不仅仅是预期的异常.
注意:替代/标准并发防止方法是无关紧要的,我想将这些知识应用于任何一般的上下文管理.我不知道不同的背景是否有不同的怪癖.
PS.该finally
块是否相关?
Hen*_*ter 27
如果上下文管理器被异常中断,则该__exit__
方法被调用为正常.事实上,传递给__exit__
所有人的参数都与处理这种情况有关!来自文档:
object.__exit__(self, exc_type, exc_value, traceback)
退出与此对象相关的运行时上下文.参数描述导致退出上下文的异常.如果在没有异常的情况下退出上下文,则所有三个参数都将为None.
如果提供了异常,并且该方法希望抑制异常(即,防止它被传播),则它应该返回一个真值.否则,在退出此方法时将正常处理异常.
请注意,
__exit__()
方法不应该重新加入传入的异常; 这是来电者的责任.
因此,您可以看到该__exit__
方法将被执行,然后,默认情况下,退出上下文管理器后将重新引发任何异常.您可以通过创建一个简单的上下文管理器并使用异常来打破它来自行测试:
DummyContextManager(object):
def __enter__(self):
print('Entering...')
def __exit__(self, exc_type, exc_value, traceback):
print('Exiting...')
# If we returned True here, any exception would be suppressed!
with DummyContextManager() as foo:
raise Exception()
Run Code Online (Sandbox Code Playgroud)
当你运行这段代码时,你应该看到你想要的一切(可能是乱序的,因为它print
往往会在追踪中间结束):
Entering...
Exiting...
Traceback (most recent call last):
File "C:\foo.py", line 8, in <module>
raise Exception()
Exception
Run Code Online (Sandbox Code Playgroud)
Dan*_*ell 13
@contextlib.contextmanager
从上面的答案中,我不太清楚使用时的最佳实践。我关注了@BenUsman评论中的链接。
如果您正在编写上下文管理器,则必须包装yield
intry-finally
块:
from contextlib import contextmanager
@contextmanager
def managed_resource(*args, **kwds):
# Code to acquire resource, e.g.:
resource = acquire_resource(*args, **kwds)
try:
yield resource
finally:
# Code to release resource, e.g.:
release_resource(resource)
>>> with managed_resource(timeout=3600) as resource:
... # Resource is released at the end of this block,
... # even if code in the block raises an exception
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
10531 次 |
最近记录: |