如何从Python中的LogRecord获取堆栈跟踪?

时间:2019-05-15 17:48:30

标签: python logging python-logging

我正在用Python实现自定义处理程序。自然,我需要重写emit(self, record)来做到这一点。一个例子:

from logging import Handler, LogRecord

class FooHandler(Handler):
    def emit(self, record: LogRecord):
        # handler logic

如您所见,每次我使用Logger实例记录内容时,都会提供LogRecordemit方法。

我从CPython源代码中看到了LogRecord的当前实现,也可以从here中看到它。

假定我有一个名为Logger的{​​{1}}实例。稍后在代码中的某处,我执行以下操作:

logger

由于@thebjorn评论了traceback模块,因此我认为可以解决此问题。但是我现在有三个问题:

  1. 如何从# either this logger.exception(Exception("foo")) # it does not have to be an instance of Exception, it's for the sake of simplicity # or this logger.error("foo", exc_info=True) # this also provides a stack trace on the console handler 实例中获取异常?
  2. 如果我执行LogRecord,则不会传递任何异常实例。在这种情况下,由于我没有简单的异常实例,如何获取回溯?

谢谢。

环境

  • Python 3.5及更高版本

2 个答案:

答案 0 :(得分:1)

我是OP,在实践中或以更Python的方式,这可能不是最佳答案,但是对于Google员工来说,有一种方法。

如问题评论中的@thebjorn所述,您需要traceback内置模块。

然后,您需要确保您要定位的异常是您的软件引发的最新异常。然后,您可以简单地致电:

traceback.print_last()

如果没有例外,那么您将获得以下字符串:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python3.7/traceback.py", line 173, in print_last
    raise ValueError("no last exception")
ValueError: no last exception

在其他情况下,您将获得最新异常的回溯:

raise Exception("foo")
traceback.print_last()

# will return a string similar to below

Traceback (most recent call last):
  File "/foo/bar/baz.py", line 3296, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "/foo/bar/biz.py", line 1, in <module>
    raise Exception("foo")
Exception: foo

希望这对Google员工有所帮助。

注意事项

如上所述,您需要确保确保所引发的最后一个异常是您要定位的异常。这可能不是一个可行的解决方案

  • 用于多线程代码库,因为您必须特别注意代码在哪个线程上运行或
  • 基于Django之类的框架构建的代码库,因为此类框架的异常处理可能会非常复杂,并且您可能会获得一个不同于您获得的异常的异常

答案 1 :(得分:1)

LogRecord 对象有一个 exc_text 属性,它看起来与回溯中提供的文本相同。当没有异常时,它返回 None

所以我认为以下内容会得到他们最初要求的 OP:

from logging import Handler, LogRecord

class FooHandler(Handler):
    def emit(self, record: LogRecord):
        print(record.exc_text)
        # other handler logic