在 Python 中记录未捕获的异常
如何使未捕获的异常通过 logging
模块输出,而不是输出到 stderr
?
我意识到做到这一点的最佳方法是:
try:
raise Exception, 'Throwing a boring exception'
except Exception, e:
logging.exception(e)
但我的情况是这样的,如果每当发生异常时自动调用 logging.exception(...)
,那就太好了异常没有被捕获。
How do you cause uncaught exceptions to output via the logging
module rather than to stderr
?
I realize the best way to do this would be:
try:
raise Exception, 'Throwing a boring exception'
except Exception, e:
logging.exception(e)
But my situation is such that it would be really nice if logging.exception(...)
were invoked automatically whenever an exception isn't caught.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
这是一个完整的小示例,其中还包括一些其他技巧:
忽略键盘中断,以便控制台 python 程序可以使用 Ctrl + C 退出。
完全依赖 python 的日志模块来格式化异常。
使用带有示例处理程序的自定义记录器。这会将未处理的异常更改为转到 stdout 而不是 stderr,但您可以以相同的样式将各种处理程序添加到记录器对象。
Here's a complete small example that also includes a few other tricks:
Ignore KeyboardInterrupt so a console python program can exit with Ctrl + C.
Rely entirely on python's logging module for formatting the exception.
Use a custom logger with an example handler. This one changes the unhandled exception to go to stdout rather than stderr, but you could add all sorts of handlers in this same style to the logger object.
正如 Ned 指出的那样,每次引发并未捕获异常时都会调用 sys.excepthook 。其实际含义是,在您的代码中,您可以覆盖 sys.excepthook 的默认行为来执行您想要的任何操作(包括使用logging.exception)。
作为一个稻草人的例子:
覆盖
sys.excepthook
:提交明显的语法错误(省略冒号)并获取自定义错误信息:
有关
sys.excepthook
的更多信息,阅读文档。As Ned pointed out,
sys.excepthook
is invoked every time an exception is raised and uncaught. The practical implication of this is that in your code you can override the default behavior ofsys.excepthook
to do whatever you want (including usinglogging.exception
).As a straw man example:
Override
sys.excepthook
:Commit obvious syntax error (leave out the colon) and get back custom error information:
For more information about
sys.excepthook
, read the docs.为什么不呢:
这是上面看到的
sys.excepthook
的输出:这是注释掉
sys.excepthook
的输出:唯一的区别是前者有 < code>ERROR:root:Unhandled exception: 在第一行的开头。
Why not:
Here is the output with
sys.excepthook
as seen above:Here is the output with the
sys.excepthook
commented out:The only difference is that the former has
ERROR:root:Unhandled exception:
at the beginning of the first line.如果未捕获异常,将调用方法
sys.excepthook
:http:// /docs.python.org/library/sys.html#sys.excepthookThe method
sys.excepthook
will be invoked if an exception is uncaught: http://docs.python.org/library/sys.html#sys.excepthook在我的例子中(使用 python 3),当使用 @Jacinda 的答案时,回溯的内容没有被打印。相反,它只是打印对象本身:
。相反,我这样做:
In my case (using
python 3
) when using @Jacinda 's answer the content of the traceback was not printed. Instead, it just prints the object itself:<traceback object at 0x7f90299b7b90>
.Instead I do:
以 Jacinda 的答案为基础,但使用记录器对象:
To build on Jacinda's answer, but using a logger object:
尽管@gnu_lorien的回答给了我一个很好的起点,但我的程序在第一个异常时崩溃了。
我提供了一个定制(和/或)改进的解决方案,它默默地记录用
@handle_error
修饰的函数的异常。Although @gnu_lorien's answer gave me good starting point, my program crashes on first exception.
I came with a customised (and/or) improved solution, which silently logs Exceptions of functions that are decorated with
@handle_error
.将您的应用程序入口调用包装在
try... except
块中,以便您能够捕获并记录(并且可能重新引发)所有未捕获的异常。例如,而不是:这样做:
Wrap your app entry call in a
try...except
block so you'll be able to catch and log (and perhaps re-raise) all uncaught exceptions. E.g. instead of:Do this:
为了回答 Zeus 先生在已接受答案的评论部分中讨论的问题,我使用它在交互式控制台中记录未捕获的异常(使用 PyCharm 2018-2019 进行测试)。我发现 sys.excepthook 不能在 python shell 中工作,所以我更深入地研究,发现我可以使用 sys.exc_info 来代替。但是,
sys.exc_info
不采用任何参数,而sys.excepthook
则采用 3 个参数。在这里,我使用 sys.excepthook 和 sys.exc_info 来在交互式控制台和带有包装器函数的脚本中记录异常。为了将钩子函数附加到这两个函数,我有两个不同的接口,具体取决于是否给出参数。
这是代码:
日志记录设置可以在 gnu_lorien 的答案中找到。
To answer the question from Mr.Zeus discussed in the comment section of the accepted answer, I use this to log uncaught exceptions in an interactive console (tested with PyCharm 2018-2019). I found out
sys.excepthook
does not work in a python shell so I looked deeper and found that I could usesys.exc_info
instead. However,sys.exc_info
takes no arguments unlikesys.excepthook
that takes 3 arguments.Here, I use both
sys.excepthook
andsys.exc_info
to log both exceptions in an interactive console and a script with a wrapper function. To attach a hook function to both functions, I have two different interfaces depending if arguments are given or not.Here's the code:
The logging setup can be found in gnu_lorien's answer.
也许您可以在模块的顶部执行一些操作,将 stderr 重定向到文件,然后在底部记录该文件
Maybe you could do something at the top of a module that redirects stderr to a file, and then logg that file at the bottom