How to set different levels for different python log handlers

后端 未结 4 799
南方客
南方客 2020-12-12 17:56

I\'ve read a few posts on this but I\'m still confused. I have this logging setup:

import logging

class MongoHandler(logging.Handler):
    def __init__(sel         


        
4条回答
  •  甜味超标
    2020-12-12 18:40

    Had the same problem but the solution didn't work for iPython as the QtConsole automatically creates a handler with no level set:

    import logging                                                                                                                               
    root = logging.getLogger()                                                                                                                   
    root.handlers                                                                                                                                
    Out: [ (NOTSET)>]
    

    As a result iPython printed both DEBUG and INFO to console in spite of having different levels for my file handler and stream handler.

    This thread pointed out this issue for me: Logging module does not print in IPython

    I made a helper module (helped greatly by this stack thread!) called custom_logging.py to make logging more convenient in other modules:

    import logging
    from pathlib import Path
    import sys
    
    def _add_stream_handler(logger: logging.Logger):
    
        stream_handler = logging.StreamHandler()
        formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
        stream_handler.setFormatter(formatter)
        stream_handler.setLevel(logging.INFO)
    
        logger.addHandler(stream_handler)
    
        return logger
    
    
    def _add_file_handler(logger: logging.Logger, log_path: Path):
    
        file_handler = logging.FileHandler(log_path, mode='w')
        formatter = logging.Formatter(
            fmt='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M')
    
        file_handler.setFormatter(formatter)
        file_handler.setLevel(logging.DEBUG)
    
        logger.addHandler(file_handler)
    
        return logger
    
    
    def create_logger(root_dir: Path, caller: str) -> logging.Logger:
    
        log_path = root_dir / 'logs' / f'{caller}.log'
        logger = logging.getLogger(caller)
        root = logging.getLogger()
    
        logger.setLevel(logging.DEBUG)
    
        # If haven't already launched handlers...
        if not len(logger.handlers):
    
            _add_file_handler(logger=logger, log_path=log_path)
            _add_stream_handler(logger=logger)
    
            logger.info('Logging started.')
    
        # Delete the Qtconsole stderr handler
        # ... as it automatically logs both DEBUG & INFO to stderr
        if root.handlers:
            root.handlers = []
    
        return logger
    
    
    def log_dataframe(df, logger: logging.Logger, name: str = "DataFrame") -> None:
    
        logger.debug(
            f'''{name} head:\n {df.head()}\n----------\n''')
    
    
    def log_dataframes(*args, logger: logging.Logger) -> None:
    
        for gdf in args:
    
            logger.debug(
                f'''DataFrame head:\n {gdf.head()}\n----------\n''')
    
    

    Can use its functions via:

    from custom_logging import create_logger, log_dataframe
    

    Or import custom_logging and custom_logging.create_logger() etc.

    Also see sections 'Multiple handlers and formatters' and 'Logging to multiple destinations' in the official logging cookbook at: https://docs.python.org/3/howto/logging-cookbook.html#logging-cookbook

提交回复
热议问题