python - 如何在上下文管理器中安全地处理异常

标签 python exception contextmanager

我想我已经读过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/

相关文章:

python - 使用具有多种数据类型的索引列表对 Pandas 系列对象进行切片

python - Python有没有像R中的quantmod一样可以下载财务报表数据的类似库?

python - 如何检查字典中的列表是否是键?

python - 在等待连接时如何关闭服务器套接字?

python - 重用 aiosqlite 连接

python - 我应该如何从 with 语句返回有趣的值?

java - Junit 参数化测试失败,并出现 java.lang.IllegalArgumentException : argument type mismatch

ios - 快速捕获无效用户输入的异常

java - Jace::虚拟机关机错误

python - 使用 threading.Lock 作为上下文管理器