【问题标题】:Custom exception default logging自定义异常默认日志
【发布时间】:2018-03-07 11:10:49
【问题描述】:

我已经构建了自定义异常,这些异常接受参数并根据常量格式化自己的消息。它们还打印到标准输出,以便用户理解问题。

例如:

defs.py:
PATH_NOT_FOUND_ERROR = 'Cannot find path "{}"'

exceptions.py:
class PathNotFound(BaseCustomException):
    """Specified path was not found."""

    def __init__(self, path):
        msg = PATH_NOT_FOUND_ERROR.format(path)
        print(msg)
        super(PathNotFound, self).__init__(msg)

some_module.py
raise PathNotFound(some_invalid_path)

我还想在抛出异常时记录它们,最简单的方法是:

logger.debug('path {} not found'.format(some_invalid_path)
raise PathNotFound(some_invalid_path)

但是在整个代码中这样做似乎是多余的,尤其是它使常量毫无意义,因为如果我决定更改措辞,我也需要更改记录器的措辞。

我试图做一些事情,比如将记录器移动到异常类,但让我失去了相关的LogRecord 属性,如namemodulefilenamelineno 等。这种方法也输了exc_info

有没有办法在每次引发之前记录异常并保留元数据而不记录?

【问题讨论】:

    标签: python exception logging


    【解决方案1】:

    如果有人感兴趣,这里有一个可行的解决方案

    这个想法是找到加注者的框架并从中提取相关信息。 还必须覆盖 logging.makeRecord 让我覆盖内部 LogRecord 属性

    设置日志记录

    class MyLogger(logging.Logger):
        """Custom Logger."""
    
        def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None, sinfo=None):
            """Override default logger to allow overridding internal attributes."""
            if six.PY2:
                rv = logging.LogRecord(name, level, fn, lno, msg, args, exc_info, func)
            else:
                rv = logging.LogRecord(name, level, fn, lno, msg, args, exc_info, func, sinfo)
    
            if extra is not None:
                for key in extra:
                    # if (key in ["message", "asctime"]) or (key in rv.__dict__):
                    #     raise KeyError("Attempt to overwrite %r in LogRecord" % key)
                    rv.__dict__[key] = extra[key]
            return rv
    
    
    
    logging.setLoggerClass(MyLogger)
    logger = logging.getLogger(__name__)
    

    自定义异常处理程序

    class BaseCustomException(Exception):
        """Specified path was not found."""
    
        def __init__(self, path):
        """Override message with defined const."""
        try:
            raise ZeroDivisionError
        except ZeroDivisionError:
            # Find the traceback frame that raised this exception
            exception_frame = sys.exc_info()[2].tb_frame.f_back.f_back
    
        exception_stack = traceback.extract_stack(exception_frame, limit=1)[0]
        filename, lineno, funcName, tb_msg = exception_stack
    
        extra = {'filename': os.path.basename(filename), 'lineno': lineno, 'funcName': funcName}
        logger.debug(msg, extra=extra)
        traceback.print_stack(exception_frame)
        super(BaseCustomException, self).__init__(msg)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-17
      • 2018-08-22
      • 2018-08-19
      • 1970-01-01
      • 2015-02-26
      • 2019-06-03
      相关资源
      最近更新 更多