我想我已经读过with
中的异常不允许正确调用__exit__
。如果我在这张纸条上有误,请原谅我的无知。
所以我这里有一些伪代码,我的目标是使用一个锁上下文,在 __enter__
记录开始日期时间并返回锁 ID,在 __exit__
记录结束日期时间并释放锁:
def main():
raise Exception
with cron.lock() as lockid:
print('Got lock: %i' % lockid)
main()
除了安全地存在上下文之外,我还能如何引发错误?
注意:我有意在此伪代码中引发基本异常,因为我想在出现任何异常时安全退出,而不仅仅是预期的异常。
注意:替代/标准的并发预防方法无关紧要,我想将这些知识应用到任何一般的上下文管理中。我不知道不同的上下文是否有不同的怪癖。
附言。 finally
block 是否相关?
最佳答案
如果上下文管理器被异常破坏,__exit__
方法被正常调用。事实上,传递给 __exit__
的参数都与处理这种情况有关!来自 the docs :
object.__exit__(self, exc_type, exc_value, traceback)
Exit the runtime context related to this object. The parameters describe the exception that caused the context to be exited. If the context was exited without an exception, all three arguments will be None.
If an exception is supplied, and the method wishes to suppress the exception (i.e., prevent it from being propagated), it should return a true value. Otherwise, the exception will be processed normally upon exit from this method.
Note that
__exit__()
methods should not reraise the passed-in exception; this is the caller’s responsibility.
因此您可以看到 __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()
当你运行这段代码时,你应该看到你想要的一切(可能是乱序的,因为 print
往往在回溯的中间结束):
Entering...
Exiting...
Traceback (most recent call last):
File "C:\foo.py", line 8, in <module>
raise Exception()
Exception
关于python - 如何在上下文管理器中安全地处理异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28157929/