我正在用logging.error将Python异常消息打印到日志文件:
import logging
try:
1/0
except ZeroDivisionError as e:
logging.error(e) # ERROR:root:division by zero
是否可以打印有关异常和生成异常的代码的更详细信息,而不仅仅是异常字符串?行号或堆栈跟踪之类的东西会很棒。
我正在用logging.error将Python异常消息打印到日志文件:
import logging
try:
1/0
except ZeroDivisionError as e:
logging.error(e) # ERROR:root:division by zero
是否可以打印有关异常和生成异常的代码的更详细信息,而不仅仅是异常字符串?行号或堆栈跟踪之类的东西会很棒。
当前回答
这个答案是建立在上述优秀答案之上的。
在大多数应用程序中,您不会直接调用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)
其他回答
如果您使用普通日志—所有日志记录都应该符合这条规则:一条记录=一行。遵循这条规则,您可以使用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)
利润!
这个答案是建立在上述优秀答案之上的。
在大多数应用程序中,您不会直接调用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)
引用
如果您的应用程序以其他方式记录日志-不使用日志模块?
现在,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(特异)
您可以记录堆栈跟踪而不出现异常。
https://docs.python.org/3/library/logging.html#logging.Logger.debug
The second optional keyword argument is stack_info, which defaults to False. If true, stack information is added to the logging message, including the actual logging call. Note that this is not the same stack information as that displayed through specifying exc_info: The former is stack frames from the bottom of the stack up to the logging call in the current thread, whereas the latter is information about stack frames which have been unwound, following an exception, while searching for exception handlers.
例子:
>>> import logging
>>> logging.basicConfig(level=logging.DEBUG)
>>> logging.getLogger().info('This prints the stack', stack_info=True)
INFO:root:This prints the stack
Stack (most recent call last):
File "<stdin>", line 1, in <module>
>>>
日志记录有一个好处。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