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

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

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


当前回答

我把所有的函数都包在我的自定义设计的日志记录器周围:

import json
import timeit
import traceback
import sys
import unidecode

def main_writer(f,argument):
  try:
    f.write(str(argument))
  except UnicodeEncodeError:
    f.write(unidecode.unidecode(argument))


def logger(*argv,logfile="log.txt",singleLine = False):
  """
  Writes Logs to LogFile
  """
  with open(logfile, 'a+') as f:
    for arg in argv:
      if arg == "{}":
        continue
      if type(arg) == dict and len(arg)!=0:
        json_object = json.dumps(arg, indent=4, default=str)
        f.write(str(json_object))
        f.flush()
        """
        for key,val in arg.items():
          f.write(str(key) + " : "+ str(val))
          f.flush()
        """
      elif type(arg) == list and len(arg)!=0:
        for each in arg:
          main_writer(f,each)
          f.write("\n")
          f.flush()
      else:
        main_writer(f,arg)
        f.flush()
      if singleLine==False:
        f.write("\n")
    if singleLine==True:
      f.write("\n")

def tryFunc(func, func_name=None, *args, **kwargs):
  """
  Time for Successfull Runs
  Exception Traceback for Unsuccessful Runs
  """
  stack = traceback.extract_stack()
  filename, codeline, funcName, text = stack[-2]
  func_name = func.__name__ if func_name is None else func_name # sys._getframe().f_code.co_name # func.__name__
  start = timeit.default_timer()
  x = None
  try:
    x = func(*args, **kwargs)
    stop = timeit.default_timer()
    # logger("Time to Run {} : {}".format(func_name, stop - start))
  except Exception as e:
    logger("Exception Occurred for {} :".format(func_name))
    logger("Basic Error Info :",e)
    logger("Full Error TraceBack :")
    # logger(e.message, e.args)
    logger(traceback.format_exc())
  return x

def bad_func():
  return 'a'+ 7

if __name__ == '__main__':
    logger(234)
    logger([1,2,3])
    logger(['a','b','c'])
    logger({'a':7,'b':8,'c':9})
    tryFunc(bad_func)

其他回答

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

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

日志记录有一个好处。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

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

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

记录器。异常将在错误消息旁边输出堆栈跟踪。

例如:

import logging
try:
    1/0
except ZeroDivisionError:
    logging.exception("message")

输出:

ERROR:root:message
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: integer division or modulo by zero

@Paulo支票笔记,“注意在python3中你必须调用日志记录。except部分中的异常方法。如果在任意位置调用此方法,可能会得到一个奇怪的异常。医生对此提出了警告。”

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

在大多数应用程序中,您不会直接调用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)