当前位置:网站首页>Encapsulating the logging module

Encapsulating the logging module

2022-04-23 16:40:00 Sink the wine cup and fleeting time

Last article , Briefly introduced Python Medium logging Log module

Simple packaging

logging Log function , It can be encapsulated into a separate module , such , Where you need to use the log function , Import this module and you can use it

my_logger.py

import logging

class LoggerHandler():

    #  initialization  Logger
    def __init__(self,
                 name='root',
                 logger_level= 'DEBUG',
                 file=None,
                 logger_format = '%(asctime)s-%(message)s'
                 # logger_format = '%(asctime)s-%(filename)s-%(lineno)d-%(message)s'
                 ):

        # 1、 initialization logger The collector 
        logger = logging.getLogger(name)


        # 2、 Set the log collector level Level 
        logger.setLevel(logger_level)

        # 5、 initialization  handler  Format 
        fmt = logging.Formatter(logger_format)

        # 3、 Initialize the log processor 

        #  If a file is passed , It will be output to file In file 
        if file:
            file_handler = logging.FileHandler(file)
            # 4、 Set up  file_handler  Level 
            file_handler.setLevel(logger_level)
            # 6、 Set up handler Format 
            file_handler.setFormatter(fmt)
            # 7、 add to handler
            logger.addHandler(file_handler)

        #  Output to the console by default 
        stream_handler = logging.StreamHandler()
        # 4、 Set up  stream_handler  Level 
        stream_handler.setLevel(logger_level)
        # 6、 Set up handler Format 
        stream_handler.setFormatter(fmt)
        # 7、 add to handler
        logger.addHandler(stream_handler)

        #  Set to instance property 
        self.logger = logger

    #  Return log information 

    def debug(self,msg):
        return self.logger.debug(msg)

    def info(self,msg):
        return self.logger.info(msg)

    def warning(self,msg):
        return self.logger.warning(msg)

    def error(self,msg):
        return self.logger.error(msg)

    def critical(self,msg):
        return self.logger.critical(msg)

such , When logs are needed , By importing my_logger modular , Use LoggerHandler Generic debug and info Function
This kind of encapsulation , The function of... Is equivalent to rewriting a log module

However , If you will init Contents of Li , Switch to logger_format = '%(asctime)s-%(filename)s-%(lineno)d-%(message)s'
This package , There will be some small problems , The line number and file will display an error

Build a new one test.py file
test.py

import my_logger

if __name__ == '__main__':
    logger = my_logger.LoggerHandler()
    logger.info('hello world!')

Execute this file , The printed content is :2021-08-29 21:12:25,462-my_logger.py-53-hello world!, The line number here is 53, The file name in the log is my_logger.py
in other words , Printed document and line number , It's in the encapsulated content , Not what we do test.py The contents of the document

The problem lies in 1、 initialization logger The collector logger = logging.getLogger(name) This step
test.py What is called in the file is LoggerHandler The content of the class ,logger When initializing , The log information has been saved , therefore , call info Function , return self.logger.info(msg) The return is LoggerHandler Class info function logger The content of

Inherit logging Modules are packaged

If we want to solve this problem , Just don't be like the above , Rewrite the function of the log module , Instead, use inheritance logging Module way , To encapsulate the log module

logging modular There is one of them. Logger class , therefore , When defining a class , Need to inherit this Logger class

Hold down Ctrl, Click on logger = logging.getLogger(name) Medium getLogger, see getLogger Contents of the method

def getLogger(name=None):
    """ Return a logger with the specified name, creating it if necessary. If no name is specified, return the root logger. """
    if name:
        return Logger.manager.getLogger(name)
    else:
        return root

The remarks are : Returns the log collector with the specified name , And create it if necessary . If no name is specified , Then return to the root log collector .
As can be seen from the remarks , What this function does , Is to return logger The collector .

Hold down Ctrl, Click on manager.getLogger(name) Medium getLogger,
There's a line of code in it : rv = (self.loggerClass or _loggerClass)(name) ,
What this line of code does , It's actually instantiating a class ( journal Logger Class ).

therefore , The above question ,1、 initialization logger The collector logger = logging.getLogger(name) This step , The instantiation is LoggerHandler class , stay test.py The log content printed in the file , The return is LoggerHandler Class info function logger Line number and file name

And adopt the way of inheritance , Inherit logging modular in Logger class , This problem will not arise , Because I'm calling theta logging modular in Logger class , Printed log content , Called is logging modular Of info Function , The returned line number and file name , That's right

therefore , There is no need to 1、 initialization logger The collector logger = logging.getLogger(name) This is the step , direct super().__init__(name) Inherit logging modular in Logger class , The corresponding content , Replace with self That's it , There is no need to customize debuginfo These methods are very effective

my_logger2.py

import logging

class LoggerHandler(logging.Logger):

    #  initialization  Logger
    def __init__(self,
                 name='root',
                 logger_level= 'DEBUG',
                 file=None,
                 logger_format = " [%(asctime)s] %(levelname)s %(filename)s [ line:%(lineno)d ] %(message)s"
                 ):

        # 1、 Set up logger The collector , Inherit logging.Logger
        super().__init__(name)


        # 2、 Set the log collector level Level 
        self.setLevel(logger_level)

        # 5、 Set up  handler  Format 
        fmt = logging.Formatter(logger_format)

        # 3、 Set up the log processor 

        #  If a file is passed , It will be output to file In file 
        if file:
            file_handler = logging.FileHandler(file)
            # 4、 Set up  file_handler  Level 
            file_handler.setLevel(logger_level)
            # 6、 Set up handler Format 
            file_handler.setFormatter(fmt)
            # 7、 add to handler
            self.addHandler(file_handler)

        #  Output to the console by default 
        stream_handler = logging.StreamHandler()
        # 4、 Set up  stream_handler  Level 
        stream_handler.setLevel(logger_level)
        # 6、 Set up handler Format 
        stream_handler.setFormatter(fmt)
        # 7、 add to handler
        self.addHandler(stream_handler)

test.py

import my_logger2

if __name__ == '__main__':
    logger = my_logger2.LoggerHandler()
    logger.info('hello world!')

perform test.py file , You can find , The log information printed is :
[2021-08-29 22:47:33,124] INFO mytest.py [ line:5 ] hello world!, That's right

If you also want to see the function name in the corresponding module in the log , You can add funcName
namely :logger_format = " [%(asctime)s] %(levelname)s [%(filename)s %(funcName)s] [ line:%(lineno)d ] %(message)s"

版权声明
本文为[Sink the wine cup and fleeting time]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204231402128384.html