【问题标题】:Correct way to handle Exception Stack Traces in Python在 Python 中处理异常堆栈跟踪的正确方法
【发布时间】:2012-04-23 14:26:57
【问题描述】:

我正在编写一些可以在堆栈深处生成异常的代码,并且我有一个更靠近顶部的层来捕获这些异常并将它们发送给错误处理模块进行处理。我希望错误处理模块能够将堆栈跟踪打印到其错误日志中,但我发现很难弄清楚这样做的方法是什么。

关于背景的一些注释:

  • 代码是多线程的,所以我不确定 sys.last_traceback 的行为

  • 我尝试在异常本身的构造函数中捕获堆栈。 sys.last_traceback 在这种情况下有时是 None (因为它只存在于未处理的异常的情况下),并不总是正确的。我目前正在玩弄使用

    self.stack = traceback.format_stack()[:-2]

在异常的构造函数中,虽然这在信息方面看起来很有希望,但感觉不是“正确”的方法

  • 我能够找到的所有如何执行此操作的示例都显示了如何在 except 块中打印堆栈跟踪,而不是在稍后的错误处理模块中,这似乎与我想要的是。 (例如,参见Print current call stack from a method in Python code

  • 我在 python 文档 (http://docs.python.org/library/traceback.html) 中挖掘了回溯模块,但无法弄清楚这是否符合我的要求。它似乎主要关注格式化回溯,因为您可能从 sys.last_traceback 检索。它有一些使用示例,但没有一个与我想要做的一致。

我不相信我是第一个想要这样做的人,所以我一定是错过了什么。任何指向正确方向的指针都非常感谢。

【问题讨论】:

  • "我能够找到的所有如何执行此操作的示例都显示了如何在 except 块中打印堆栈跟踪,而不是在以后的一些错误处理模块中,这似乎有所不同在我想要的行为中。”我不明白怎么做。展示一个示例,以及预期和实际的输出。
  • 嗨@KarlKnechtel - 我发现的另一个例子是doughellmann.com/PyMOTW/traceback 在except 块中使用print_exc() 报告了错误,但是当我在except 块之外使用这个函数时,我什么也得不到(无)
  • 所以...它只能在 except 块内工作。但重点是抛出异常,然后,“靠近顶部的一层会捕获这些异常”。那么在 that 除了块之外这样做有什么问题呢?

标签: python exception error-handling stack-trace printstacktrace


【解决方案1】:

如果我理解正确,您想在保留堆栈跟踪的同时重新引发异常吗?所以你有一个这样的调用层次结构:

error_handling_module # you want to print the stacktrace here
|
something_else
|
module_excepting_and_rethrowing
|
something_else
|
module_raising_an_error

在你的 module_excepting_and_rethrowing 中你可以这样做:

except Exception:
   exc_type, exc_value, exc_traceback = sys.exc_info()
   raise NewException, exc_value, exc_traceback

在 Python3 中你也可以这样做:

 except Exception as e:
     raise NewException from e

【讨论】:

    【解决方案2】:

    在你想保护的函数中添加一些装饰器怎么样?例如:

    @onerrorignore
    def foo(a, b, c):
        ...
    

    装饰器看起来像:

    def onerrorignore(f):
        def _f(*args, **kwargs):
            try:
                ret = f()
            except:
                error_handler.handle(sys.exc_info())
            else:
                return ret
        return _f
    

    【讨论】:

      【解决方案3】:

      您处理异常的第一行可能是:

      exc_type, exc_value, exc_traceback = sys.exc_info()
      

      您可以存储这些变量或以任何您喜欢的方式传递它们,然后使用回溯模块显示它们。

      【讨论】:

      • 嗨@ali-afshar - 是的,我想知道使用这样的东西,但缺点是这需要出现在每个 except 块中,然后将变量分配给异常的某些属性,例如。这给开发人员带来了记住这样做的负担,并使错误更容易引入。将这行代码 /inside/ 设置为异常构造函数会更好,但这似乎不起作用。
      • @RichardJ:请注意,并非所有异常都会在构造它们的地方抛出,虽然对于大多数异常来说都是如此,但严格来说假设是不正确的。
      • “缺点是它需要出现在每个 except 块中”......但我认为你设计的重点是你让所有异常都落入一个 except 块更高!
      • 整件事情都被打破了。
      猜你喜欢
      • 2012-09-21
      • 1970-01-01
      • 2017-05-08
      • 1970-01-01
      • 2011-01-05
      • 2023-03-14
      • 1970-01-01
      • 2013-07-31
      • 1970-01-01
      相关资源
      最近更新 更多