[英]How do I Get Stack Trace from LogRecord in Python?
I am implementing a custom Handler with Python.我正在用 Python 实现一个自定义处理程序。 Naturally, I need to override
emit(self, record)
to do that.自然,我需要重写
emit(self, record)
来做到这一点。 An example:一个例子:
from logging import Handler, LogRecord
class FooHandler(Handler):
def emit(self, record: LogRecord):
# handler logic
As you can see, everytime I log something with a Logger
instance, this will provide a LogRecord
to emit
method.如您所见,每次我使用
Logger
实例记录某些内容时,这将提供一个LogRecord
来emit
方法。
I see the current implementation of LogRecord
from CPython source, you can also see it from here .我从 CPython 源代码中看到了
LogRecord
的当前实现,您也可以从这里看到它。
Assuming I have Logger
instance called logger
.假设我有一个名为
logger
的Logger
实例。 Later somewhere in the code, I do these:稍后在代码中的某处,我执行以下操作:
# 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
Since @thebjorn has commented about traceback module, I think I can work around from that.由于@thebjorn 评论了回溯模块,我想我可以解决这个问题。 However I have three questions right now:
但是我现在有三个问题:
LogRecord
instance?LogRecord
实例中获取异常?logger.error("message", exc_info=True)
, then I do not pass any exception instance.logger.error("message", exc_info=True)
,那么我不会传递任何异常实例。 In this case, how do I get the traceback since I do not simply have any exception instance? Thanks in advance.提前致谢。
I am the OP and this may not be the best answer, in practice or more Pythonic way but, for Googlers, there is a method.我是 OP,这可能不是最好的答案,在实践中或更 Pythonic 的方式,但对于谷歌人来说,有一种方法。
As @thebjorn stated in the comments of the question, you need traceback built-in module.正如@thebjorn在问题评论中所述,您需要回溯内置模块。
Then you need to make sure that the exception you are targeting is the latest exception your software has raised.然后,您需要确保您所针对的异常是您的软件引发的最新异常。 Then you can simply call:
然后你可以简单地调用:
traceback.print_last()
If there is no exception, then you will get below as a string:如果没有例外,那么您将得到以下字符串:
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
In other case, you will get the latest exception's traceback:在其他情况下,您将获得最新异常的回溯:
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
Hope this helps to Googlers.希望这对 Google 员工有所帮助。
As I've mentioned, you will need to make sure that the last exception that has got raised is the exception that you are targeting.正如我所提到的,您需要确保引发的最后一个异常是您所针对的异常。 This might not be a viable solution
这可能不是一个可行的解决方案
The LogRecord object has an exc_text
attribute that looks to be identical to the text provided in a traceback. LogRecord 对象有一个
exc_text
属性,该属性看起来与回溯中提供的文本相同。 It returns None
when there isn't an exception.没有异常时返回
None
。
So I think the following would get the OP what they were originally requesting:所以我认为以下内容会得到他们最初要求的 OP:
from logging import Handler, LogRecord
class FooHandler(Handler):
def emit(self, record: LogRecord):
print(record.exc_text)
# other handler logic
Expanding upon sazerac's code, exec_text didn't have any value when I ran it with a sample try except block, but exc_info WAS populated.扩展 sazerac 的代码,当我使用除块之外的示例尝试运行 exec_text 时,它没有任何价值,但 exc_info 已填充。 This is what I used to work around my scenario.
这就是我用来解决我的场景的方法。
from logging import Handler, LogRecord
import traceback
class FooHandler(Handler):
def emit(self, record: LogRecord):
if record.exc_info:
errType, errValue, errTraceback = record.exc_info
msg = "".join(traceback.format_exception(errType, errValue, errTraceback))
else:
msg = ''
print(msg)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.