python如何安全地处理上下文管理器中的异常 [英] python how to safely handle an exception inside a context manager

查看:222
本文介绍了python如何安全地处理上下文管理器中的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想我已经读到 with 中的异常不允许正确调用 __ exit __ 。如果我错了,请原谅我的无知。

I think I've read that exceptions inside a with do not allow __exit__ to be call correctly. If I am wrong on this note, pardon my ignorance.

所以我这里有一些伪代码,我的目标是使用一个 __ enter __ 记录开始日期时间并返回锁ID,并在 __ exit __ 记录结束日期时间并释放锁:

So I have some pseudo code here, my goal is to use a lock context that upon __enter__ logs a start datetime and returns a lock id, and upon __exit__ records an end datetime and releases the lock:

def main():
    raise Exception

with cron.lock() as lockid:
    print('Got lock: %i' % lockid)
    main()

如何除了安全地存在上下文之外,我还会引发错误吗?

How can I still raise errors in addition to existing the context safely?

注意:由于我想安全退出,因此我故意在此伪代码中引发了基本异常任何异常,而不仅仅是预期的异常。

注意:替代/标准并发预防方法无关紧要,我想将此知识应用于任何常规我不知道不同的上下文是否有不同的怪癖。

Note: Alternative/standard concurrency prevention methods are irrelevant, I want to apply this knowledge to any general context management. I do not know if different contexts have different quirks.

PS。 最终块是否相关?

PS. Is the finally block relevant?

推荐答案

__ exit __ 方法通常会被调用。实际上,传递给 __ exit __ 的参数都与处理这种情况有关!来自文档

The __exit__ method is called as normal if the context manager is broken by an exception. In fact, the parameters passed to __exit__ all have to do with handling this case! From the docs:


object .__ exit __(self,exc_type,exc_value,traceback)

退出与此对象相关的运行时上下文。参数描述导致上下文退出的异常。如果没有异常退出上下文,则所有三个参数均为None。

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.

请注意, __ exit __()方法不应重传传入的异常;

Note that __exit__() methods should not reraise the passed-in exception; this is the caller’s responsibility.

因此您可以看到 __ exit __ 方法将被执行,然后默认情况下,退出上下文管理器后 将重新引发任何异常。您可以通过创建一个简单的上下文管理器并使用异常将其断开来进行测试:

So you can see that the __exit__ method will be executed and then, by default, any exception will be re-raised after exiting the context manager. You can test this yourself by creating a simple context manager and breaking it with an exception:

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 往往会在回溯过程中结束,因此可能会出现故障):

When you run this code, you should see everything you want (might be out of order since print tends to end up in the middle of tracebacks):

Entering...
Exiting...
Traceback (most recent call last):
  File "C:\foo.py", line 8, in <module>
    raise Exception()
Exception

这篇关于python如何安全地处理上下文管理器中的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆