我正在用logging.error将Python异常消息打印到日志文件:

import logging
try:
    1/0
except ZeroDivisionError as e:
    logging.error(e)  # ERROR:root:division by zero

是否可以打印有关异常和生成异常的代码的更详细信息,而不仅仅是异常字符串?行号或堆栈跟踪之类的东西会很棒。


当前回答

引用

如果您的应用程序以其他方式记录日志-不使用日志模块?

现在,traceback可以用在这里。

import traceback

def log_traceback(ex, ex_traceback=None):
    if ex_traceback is None:
        ex_traceback = ex.__traceback__
    tb_lines = [ line.rstrip('\n') for line in
                 traceback.format_exception(ex.__class__, ex, ex_traceback)]
    exception_logger.log(tb_lines)

在Python 2中使用它: 试一试: #你的函数调用在这里 Exception as ex: _, _, ex_traceback = sys.exc_info() ex_traceback log_traceback(例) 在Python 3中使用它: 试一试: X = get_number() Exception as ex: log_traceback(特异)

其他回答

这个答案是建立在上述优秀答案之上的。

在大多数应用程序中,您不会直接调用logging.exception(e)。很可能你已经为你的应用程序或模块定义了一个自定义记录器,如下所示:

# Set the name of the app or module
my_logger = logging.getLogger('NEM Sequencer')
# Set the log level
my_logger.setLevel(logging.INFO)

# Let's say we want to be fancy and log to a graylog2 log server
graylog_handler = graypy.GELFHandler('some_server_ip', 12201)
graylog_handler.setLevel(logging.INFO)
my_logger.addHandler(graylog_handler)

在这种情况下,只需使用记录器调用异常(e),如下所示:

try:
    1/0
except ZeroDivisionError, e:
    my_logger.exception(e)

在日志模块(如果是自定义模块)中启用stack_info。

api_logger.exceptionLog("*Input your Custom error message*",stack_info=True)

使用exc_info选项可能更好,允许你选择错误级别(如果你使用exception,它将总是在错误级别):

try:
    # do something here
except Exception as e:
    logging.critical(e, exc_info=True)  # log exception info at CRITICAL log level

如果您使用普通日志—所有日志记录都应该符合这条规则:一条记录=一行。遵循这条规则,您可以使用grep和其他工具来处理日志文件。

但是回溯信息是多行的。所以我的答案是zangw在这篇文章中提出的解决方案的扩展版本。问题是回溯行内部可能有\n,所以我们需要做额外的工作来消除这些行结束符:

import logging


logger = logging.getLogger('your_logger_here')

def log_app_error(e: BaseException, level=logging.ERROR) -> None:
    e_traceback = traceback.format_exception(e.__class__, e, e.__traceback__)
    traceback_lines = []
    for line in [line.rstrip('\n') for line in e_traceback]:
        traceback_lines.extend(line.splitlines())
    logger.log(level, traceback_lines.__str__())

在这之后(当你分析你的日志时),你可以从你的日志文件中复制/粘贴所需的回溯行,并这样做:

ex_traceback = ['line 1', 'line 2', ...]
for line in ex_traceback:
    print(line)

利润!

日志记录有一个好处。SiggyF的答案没有显示的异常是,你可以传递一个任意的消息,日志仍然会显示所有异常细节的完整跟踪:

import logging
try:
    1/0
except ZeroDivisionError:
    logging.exception("Deliberate divide by zero traceback")

默认情况下(在最近的版本中)只是将错误打印到sys. log行为。Stderr,它看起来像这样:

>>> import logging
>>> try:
...     1/0
... except ZeroDivisionError:
...     logging.exception("Deliberate divide by zero traceback")
... 
ERROR:root:Deliberate divide by zero traceback
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: integer division or modulo by zero