简体   繁体   English

有什么方法可以访问 python 中的嵌套或重新引发的异常?

[英]Is there any way to access nested or re-raised exceptions in python?

A common pattern in python is to catch an error in an upstream module and re-raise that error as something more useful. python 中的一个常见模式是捕获上游模块中的错误并将该错误重新引发为更有用的东西。

try:
    config_file = open('config.ini', 'r')
except IOError:
    raise ConfigError('Give me my config, user!')

This will generate a stack trace of the form这将生成表单的堆栈跟踪

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
__main__.ConfigError: Give me my config, user!

Is there any way to access the wrapped exception in order to generate a stack trace more like this?有没有办法访问包装的异常以生成更像这样的堆栈跟踪?

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
__builtin__.IOError: File Does not exist.
Exception wrapped by:
  File "<stdin>", line 4, in <module>
__main__.ConfigError: Give me my config, user!

EDIT:编辑:

The problem i'm trying to defeat is that some 3rd party code can wrap exceptions up to 3 times and I want to be able to determine the root cause, ie a generic way to inspect the exception stack and determine the root cause of an exception without having to add any extra code to 3rd party modules.我试图解决的问题是一些第 3 方代码最多可以包装异常 3 次,我希望能够确定根本原因,即检查异常堆栈并确定异常根本原因的通用方法无需向 3rd 方模块添加任何额外代码。

This is known as Exception Chaining and is suported in Python 3. 这被称为异常链接,并在Python 3中被支持。

PEP 3134: http://www.python.org/dev/peps/pep-3134/ PEP 3134: http ://www.python.org/dev/peps/pep-3134/

In Python 2, the old exception is lost when you raise a new one, unless you save it in the except block. 在Python 2中,除非将其保存在except块中,否则在引发新异常时会丢失旧异常。

Use the traceback module . 使用traceback 模块 It will allow you to access the most recent traceback and store it in a string. 它将允许您访问最新的回溯并将其存储在字符串中。 For example, 例如,

import traceback
try:
    config_file = open('config.ini', 'r')
except OSError:
    tb = traceback.format_exc()
    raise ConfigError('Give me my config, user!',tb)

The "nested" traceback will be stored in tb and passed to ConfigError, where you can work with it however you want. “嵌套”回溯将存储在tb中并传递给ConfigError,您可以根据需要使用它。

Here is an example of how to unwind PEP-3134 exception chains.这是一个如何展开PEP-3134异常链的示例。

Note that due to legacy reasons some Python frameworks may not use exception chaining, but instead of wrap exceptions in their own way.请注意,由于遗留原因,一些 Python 框架可能不使用异常链,而是以自己的方式包装异常。 For example.例如。 SQLALchemy DBABIError uses orig attribute . SQLALchemy DBABIError 使用orig属性

class Foobar(Exception):
    pass


class Dummy(Exception):
    pass


def func1():
    raise Foobar("func1() argh")


def func2():
    try:
        func1()
    except Exception as e:
        raise Dummy("func2 vyaaarrg!") from e

try:
    func2()
except Exception as e:
    print(f"Current {e.__class__}: {e}")
    print(f"Nested {e.__cause__.__class__}:{e.__cause__}")

Prints印刷

Current <class '__main__.Dummy'>: func2 vyaaarrg!
Nested <class '__main__.Foobar'>:func1() argh

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM