0

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

from logging import Handler, LogRecord

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

如您所见,每次我使用Logger实例记录某些内容时,这将提供一个LogRecordtoemit方法。

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

假设我有Logger一个名为logger. 稍后在代码中的某个地方,我执行以下操作:

# 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

由于@thebjorn 评论了回溯模块,我想我可以解决这个问题。但是我现在有三个问题:

  1. 如何从LogRecord实例中获取异常?
  2. 如果我这样做logger.error("message", exc_info=True),那么我不会传递任何异常实例。在这种情况下,我如何获得回溯,因为我没有任何异常实例?

提前致谢。

环境

  • Python 3.5 及以上
4

2 回答 2

1

我是 OP,这可能不是最好的答案,在实践中或更 Pythonic 的方式,但对于谷歌人来说,有一种方法。

正如@thebjorn在问题评论中所述,您需要回溯内置模块。

然后,您需要确保您所针对的异常是您的软件引发的最新异常。然后你可以简单地调用:

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 等框架构建的代码库,因为此类框架的异常处理可能非常复杂,并且您可能会得到一个不同的异常,而不是您想要得到的异常
于 2019-05-15T18:15:17.327 回答
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
于 2021-02-15T23:03:25.747 回答