我可以通过日志记录在一行中输出 Python 异常吗?

Can I make Python output exceptions in one line / via logging?

我正在使用 AWS 并使用 AWS cloudwatch 查看日志。虽然事情不应该在 AWS 上崩溃,但它们可能会崩溃。我刚好有这样一个案例。然后我搜索 Traceback 并得到行

Traceback (most recent call last):

没有实际的回溯。我有一个有效的结构化日志记录设置(参见 ),我想以类似的方式获得回溯。

所以代替:

Traceback (most recent call last):
  File "/home/math/Desktop/test.py", line 32, in <module>
    adf
NameError: name 'adf' is not defined

类似

{"message": "Traceback (most recent call last):\n      File \"/home/math/Desktop/test.py\", line 32, in <module>\n        adf\n    NameError: name 'adf' is not defined", "lineno": 35, "pathname": "/home/math/Desktop/test.py"}

甚至更好,还可以使用 JSON 格式的字符串。

我能想到的实现这一点的唯一方法是一个巨大的 try-except 块。宠物小精灵风格。有更好的解决方案吗?

您可以使用 sys.excepthook。每当脚本中发生异常时都会调用它。

import logging
import sys
import traceback

def exception_logging(exctype, value, tb):
    """
    Log exception by using the root logger.

    Parameters
    ----------
    exctype : type
    value : NameError
    tb : traceback
    """
    write_val = {'exception_type': str(exctype),
                 'message': str(traceback.format_tb(tb, 10))}
    logging.exception(str(write_val))

然后在您的脚本中您必须覆盖 sys.excepthook 的值。

sys.excepthook = exception_logging

现在,无论何时发生异常,都会使用您的记录器处理程序进行记录。

注意:不要忘记在 运行 这个

之前设置记录器

如果有人希望以默认格式记录异常,但基于接受的答案(出于任何原因)在一行中:

def exception_logging(exctype, value, tb):
    """
    Log exception in one line by using the root logger.

    Parameters
    ----------
    exctype : exception type
    value : seems to be the Exception object (with its message)
    tb : traceback
    """
    logging.error(''.join(traceback.format_exception(exctype, value, tb)))

另请注意,它使用 logging.error() 而不是 logging.exception(),后者还打印了一些额外的 "NoneType: None" 行。
另请注意,它似乎只适用于未捕获的异常。
要记录捕获的异常,请访问 并查看我的回答。

一个细微的变化:如果你运行一个 Flask 应用程序,你可以这样做:

@app.errorhandler(Exception)
def exception_logger(error):
    """Log the exception."""
    logger.exception(str(error))
    return str(error)