Python logging: disable stack trace

后端 未结 1 1216
感动是毒
感动是毒 2021-02-14 10:06

Is there a simple way to disable the logging of an exception stack trace in Python 3, either in a Handler or Formatter?

I need the stack trace

相关标签:
1条回答
  • 2021-02-14 10:46

    The easiest option to disable per handler traceback output is to add a custom logging.Filter subclass that alters the record object (rather than filter out records).

    The filter simply has to set exc_info on records to None:

    class TracebackInfoFilter(logging.Filter):
        """Clear or restore the exception on log records"""
        def __init__(self, clear=True):
            self.clear = clear
        def filter(self, record):
            if self.clear:
                record._exc_info_hidden, record.exc_info = record.exc_info, None
                # clear the exception traceback text cache, if created.
                record.exc_text = None
            elif hasattr(record, "_exc_info_hidden"):
                record.exc_info = record._exc_info_hidden
                del record._exc_info_hidden
            return True
    

    and add that filter on your handler:

    # do not display tracebacks in messages handled with this handler,
    # by setting the traceback cache to a non-empty string:
    handler_with_no_tracebacks.addFilter(TracebackInfoFilter())
    

    However, handlers do not copy log records, and any other handler that is passed the same log record later on will also ignore formatting the traceback. So you also need to configure any other handlers to restore the information again:

    for handler in logger.handlers:
        if not any(isinstance(f, TracebackInfoFilter) for f in handler.filters):
            handler.addFilter(TracebackInfoFilter(clear=False))
    

    If anyone wanted to disable all traceback outputs, everywhere, then perhaps adding a custom filter to all handlers or loggers becomes tedious. In that case another option is to register a custom record factory with the logging.setLogRecordFactory() function; just set the exc_info attribute on records to None, unconditionally:

    record_factory = logging.getLogRecordFactory()
    
    def clear_exc_text(*args, **kwargs):
        record = record_factory(*args, **kwargs)
        record.exc_info = None
        return record
    
    logging.setLogRecordFactory(clear_exc_text)
    

    Note that the default factory is just the logging.LogRecord class, but the above function does its best to work with any already-set custom factory.

    Of course, you can also create your own Handler subclass where the Handler.handle() sets and clears the exc_info attribute:

    class NoTracebackHandler(logging.Handler):
        def handle(self, record):
            info, cache = record.exc_info, record.exc_text
            record.exc_info, record.exc_text = None, None
            try:
                super().handle(record)
            finally:
                record.exc_info = info
                record.exc_text = cache
    
    0 讨论(0)
提交回复
热议问题