如何记录带有调试信息的 Python 错误?
我使用 logging.error
将 Python 异常消息打印到日志文件:
import logging
try:
1/0
except ZeroDivisionError as e:
logging.error(e) # ERROR:root:division by zero
是否可以打印有关异常和生成异常的代码的更多详细信息,而不仅仅是异常字符串?像行号或堆栈跟踪这样的东西会很棒。
I am printing Python exception messages to a log file with logging.error
:
import logging
try:
1/0
except ZeroDivisionError as e:
logging.error(e) # ERROR:root:division by zero
Is it possible to print more detailed information about the exception and the code that generated it than just the exception string? Things like line numbers or stack traces would be great.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
logger.exception
将输出堆栈跟踪与错误消息一起。例如:
输出:
@Paulo Cheque 注释,“请注意,在 Python 3 中,您必须调用
logging.exception
方法就在except
部分中,如果您在任意位置调用此方法,您可能会收到一个奇怪的异常。”logger.exception
will output a stack trace alongside the error message.For example:
Output:
@Paulo Cheque notes, "be aware that in Python 3 you must call the
logging.exception
method just inside theexcept
part. If you call this method in an arbitrary place you may get a bizarre exception. The docs alert about that."使用
exc_info
选项可能会更好,允许您选择错误级别(如果您使用exception
,它将始终处于error
级别):Using
exc_info
options may be better, to allow you to choose the error level (if you useexception
, it will always be at theerror
level):SiggyF 的答案 没有显示的关于
logging.exception
的一个好处是,您可以传入一个任意消息,并且日志记录仍将显示包含所有异常详细信息的完整回溯:默认(在最新版本中)日志记录行为仅将错误打印到 sys.stderr ,它看起来像这样:
One nice thing about
logging.exception
that SiggyF's answer doesn't show is that you can pass in an arbitrary message, and logging will still show the full traceback with all the exception details:With the default (in recent versions) logging behaviour of just printing errors to
sys.stderr
, it looks like this:引用
现在,可以在这里使用
traceback
。在Python 2中使用它:
<前><代码>尝试:
# 你的函数调用在这里
除了异常例如:
_、_、ex_traceback = sys.exc_info()
log_traceback(前,ex_traceback)
在Python 3中使用它:
<前><代码>尝试:
x = get_number()
除了异常例如:
log_traceback(前)
Quoting
Now,
traceback
could be used here.Use it in Python 2:
Use it in Python 3:
您可以毫无异常地记录堆栈跟踪。
https://docs.python.org/3/library/logging .html#logging.Logger.debug
例子:
You can log the stack trace without an exception.
https://docs.python.org/3/library/logging.html#logging.Logger.debug
Example:
如果您使用纯日志 - 所有日志记录都应符合以下规则:
一条记录 = 一行
。遵循此规则,您可以使用grep
和其他工具来处理日志文件。但回溯信息是多行的。所以我的答案是上面的 zangw 提出的解决方案的扩展版本。问题是回溯行可能有
\n
内部,所以我们需要做额外的工作来摆脱这个行结尾:之后(当你分析你的日志时)你可以复制/ 从日志文件中粘贴所需的回溯行并执行以下操作:
利润!
If you use plain logs - all your log records should correspond this rule:
one record = one line
. Following this rule you can usegrep
and other tools to process your log files.But traceback information is multi-line. So my answer is an extended version of solution proposed by zangw above in this thread. The problem is that traceback lines could have
\n
inside, so we need to do an extra work to get rid of this line endings:After that (when you'll be analyzing your logs) you could copy / paste required traceback lines from your log file and do this:
Profit!
这个答案是建立在上述优秀答案的基础上的。
在大多数应用程序中,您不会直接调用logging.exception(e)。您很可能已经为您的应用程序或模块定义了一个特定的自定义记录器,如下所示:
在这种情况下,只需使用记录器来调用异常(e),如下所示:
This answer builds up from the above excellent ones.
In most applications, you won't be calling logging.exception(e) directly. Most likely you have defined a custom logger specific for your application or module like this:
In this case, just use the logger to call the exception(e) like this:
如果“调试信息”是指引发异常时出现的值,那么
logging.exception(...)
将无济于事。因此,您需要一个工具来自动记录所有变量值以及回溯行。开箱即用,你会得到类似“
看看一些 pypi 工具,我命名为:
其中一些会给你漂亮的崩溃消息:
但您可能会在 pypi 上找到更多信息
If "debugging information" means the values present when exception was raised, then
logging.exception(...)
won't help. So you'll need a tool that logs all variable values along with the traceback lines automatically.Out of the box you'll get log like
Have a look at some pypi tools, I'd name:
Some of them give you pretty crash messages:
But you might find some more on pypi
从 Python 3.5 开始,可以在
日志记录函数中显式指定异常:logging.exception 函数仍然有效,但必须仅在 except 块内调用,并且不允许指定日志级别。
Since Python 3.5, it's possible to explicitly specify the exception in the logging function:
The
logging.exception
function still works but must be called only within theexcept
block and does not allow specifying log level.一点装饰器处理(非常松散地受到 Maybe monad 和提升的启发)。您可以安全地删除 Python 3.6 类型注释并使用较旧的消息格式样式。
fallible.py
演示:
您还可以修改此解决方案,以从
except
部分返回比None
更有意义的内容(或者甚至使解决方案通用,通过在fallible
的参数中指定此返回值)。A little bit of decorator treatment (very loosely inspired by the Maybe monad and lifting). You can safely remove Python 3.6 type annotations and use an older message formatting style.
fallible.py
Demo:
You can also modify this solution to return something a bit more meaningful than
None
from theexcept
part (or even make the solution generic, by specifying this return value infallible
's arguments).在您的日志记录模块(如果是自定义模块)中,只需启用 stack_info。
In your logging module(if custom module) just enable stack_info.
如果您查看此代码示例(适用于Python 2和3),您会请参阅下面的函数定义,它可以提取
,无论是否存在异常:
当然,这个函数取决于上面链接的整个要点,特别是
extract_all_sentry_frames_from_exception()
和frame_trans()
,但异常信息提取总共不到 60 行左右。希望有帮助!
If you look at the this code example (which works for Python 2 and 3) you'll see the function definition below which can extract
for an entire stack trace, whether or not there has been an exception:
Of course, this function depends on the entire gist linked above, and in particular
extract_all_sentry_frames_from_exception()
andframe_trans()
but the exception info extraction totals less than around 60 lines.Hope that helps!
我将所有功能包装在我的定制设计的记录器中:
I wrap all functions around my custom designed logger:
执行此操作的最佳且最小的库是
loguru
,它显示内置的回溯并提供调试信息:输出:
The best and minimal library for doing this is
loguru
, which shows an in-baked traceback and provides debug info:Outputs:
我的方法是创建一个上下文管理器,用于记录和引发异常:
您可以将记录器名称或记录器实例传递给
LogError()
。默认情况下,它将使用基本记录器(通过将None
传递给logging.getLogger)。人们还可以简单地添加一个开关来引发错误或只是记录错误。
My approach was to create a context manager, to log and raise Exceptions:
You can either pass a logger name or a logger instance to
LogError()
. By default it will use the base logger (by passingNone
to logging.getLogger).One could also simply add a switch for raising the error or just logging it.
如果您可以处理额外的依赖关系,则使用twisted.log,您不必显式记录错误,并且它还会将整个回溯和时间返回到文件或流。
If you can cope with the extra dependency then use twisted.log, you don't have to explicitly log errors and also it returns the entire traceback and time to the file or stream.
一种干净的方法是使用
format_exc()
然后解析输出以获取相关部分:问候
A clean way to do it is using
format_exc()
and then parse the output to get the relevant part:Regards