如何记录python异常?

Max*_*ler 69 python logging exception-handling

如何在Python中记录异常?

我查看了一些选项,发现我可以使用以下代码访问实际的异常详细信息:

import sys
import traceback

try:
    1/0
except:
    exc_type, exc_value, exc_traceback = sys.exc_info()
    traceback.print_exception(exc_type, exc_value, exc_traceback)
Run Code Online (Sandbox Code Playgroud)

我想以某种方式将字符串print_exception()抛出到stdout以便我可以记录它.

rlo*_*tun 109

看看logging.exception(Python日志模块)

import logging 
def foo():
    try:
        some_code()
    except:
        logging.exception('')
Run Code Online (Sandbox Code Playgroud)

这应该自动处理获取当前异常的回溯并正确记录它.

  • `除了`catch-all可能是一个坏主意:http://stackoverflow.com/a/4990739/1091116 (3认同)

Ben*_*oyt 59

要回答您的问题,您可以获得print_exception()使用该traceback.format_exception()函数的字符串版本.它将traceback消息作为字符串列表返回,而不是将其打印到stdout,因此您可以使用它执行所需的操作.例如:

import sys
import traceback

try:
    asdf
except NameError:
    exc_type, exc_value, exc_traceback = sys.exc_info()
    lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
    print ''.join('!! ' + line for line in lines)  # Log it or whatever here
Run Code Online (Sandbox Code Playgroud)

这显示:

!! Traceback (most recent call last):
!!   File "<stdin>", line 2, in <module>
!! NameError: name 'asdf' is not defined
Run Code Online (Sandbox Code Playgroud)

但是,我肯定建议使用标准的Python日志记录模块,如rlotun所建议的那样.这不是最简单的设置,但它是非常可定制的.

  • "不是最简单的设置方式",这意味着它很难设置,但事实并非如此,主函数中的`logging.basicConfig()`足以满足大多数简单应用程序的要求. (4认同)
  • 当您无法使用日志记录包时,您的代码很有用。例如,当实现日志处理程序时:-) (2认同)
  • @Doomsday,我认为实现一个[`logging.Handler`](https://docs.python.org/library/logging.html#handler-objects)可能是这个代码的唯一好处.对于OP的原始问题,OP应该使用[logging](http://docs.python.org/library/logging.html)和`logging.exception`,或者使用`exc_info = True`在较低级别登录. (2认同)

Nei*_*ais 51

记录异常就像在任何日志消息中添加exc_info = True关键字参数一样简单,请参阅http://docs.python.org/2/library/logging.html中的 Logger.debug条目.

例:

try: 
    raise Exception('lala')
except Exception:
    logging.info('blah', exc_info=True)
Run Code Online (Sandbox Code Playgroud)

输出(当然,取决于您的日志处理程序配置):

2012-11-29 10:18:12,778 - root - INFO - <ipython-input-27-5af852892344> : 3 - blah
Traceback (most recent call last):
  File "<ipython-input-27-5af852892344>", line 1, in <module>
    try: raise Exception('lala')
Exception: lala
Run Code Online (Sandbox Code Playgroud)

  • logging.exception是logging.error(...,exc_info = True)的缩写,因此如果您打算将异常记录为错误,那么最好使用logging.exception.如果要在除错误之外的日志级别记录格式化异常,则必须使用exc_info = True. (5认同)
  • 你需要付出很多努力.为什么不只是`logging.exception(exc)`? (2认同)
  • “显式优于隐式” (2认同)

yur*_*rez 17

在Python 3.5中,您可以在exc_info参数中传递异常实例:

import logging
try:
    1/0
except Exception as e:
   logging.error('Error at %s', 'division', exc_info=e)
Run Code Online (Sandbox Code Playgroud)

  • 或者直接使用“logging.exception("..")”,它会自动记录回溯。 (4认同)
  • 这正是我想要的。我需要记录一个[任务异常](https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.exception)并且没有 except 块。 (2认同)

eri*_*krf 5

首先,考虑在except子句中使用适当的Exception类型.然后,命名异常,您可以打印它:

try:
    1/0
except Exception as e:
    print e
Run Code Online (Sandbox Code Playgroud)

依赖于您的Python版本,您必须使用

except Exception, e
Run Code Online (Sandbox Code Playgroud)

  • @ChrisJohnson你在本页的一些评论中推荐了`logging.exception(exc)`,但这是一个坏主意.`logging.exception`的第一个参数不是用于记录的异常(Python只是从当前的`except:`block by magic)获取一个参数,它是在回溯之前记录的*message*.将异常指定为消息会导致将其转换为字符串,从而导致异常消息重复.如果您没有有意义的消息来记录您的异常,请使用`logging.exception('')`,但`logging.exception(exc)`没有意义. (7认同)
  • 打印不记录.使用`logging.exception(exc)`. (4认同)