python logging module instances and improvements

  • 2020-05-26 09:30:09
  • OfStack

python prints all property values of the object:


def prn_obj(obj):
  print '\n'.join(['%s:%s' % item for item in obj.__dict__.items()])

Python logger object properties (obtained by the above function)


name:get_data
parent:<logging.RootLogger instance at 0x1d8bd88>
handlers:[<logging.FileHandler instance at 0x21bcc68>]
level:10
disabled:1   # The current logger If it is valid, the default is 0
manager:<logging.Manager instance at 0x1d8bea8>
propagate:0   # Whether to log this level 
filters:[]
 

Some logs could not be output

File: logger conf


 
[formatters]
keys=default
 
[formatter_default]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
class=logging.Formatter
 
[handlers]
keys=console, error_file
 
[handler_console]
class=logging.StreamHandler
formatter=default
args=tuple()
 
[handler_error_file]
class=logging.FileHandler
level=INFO
formatter=default
args=("logger.log", "a")
 
[loggers]
keys=root
 
[logger_root]
level=DEBUG
formatter=default
handlers=console,error_file

File: logger py


 
#!/bin/env python
 
import logging
from logging.config import logging
 
class Test(object):
  """docstring for Test"""
  def __init__(self):
    logging.config.fileConfig("logger.conf")
    self.logger = logging.getLogger(__name__)
 
  def test_func(self):
    self.logger.error('test_func function')
 
class Worker(object):
  """docstring for Worker"""
  def __init__(self):
    logging.config.fileConfig("logger.conf")
    self.logger = logging.getLogger(__name__)
 
    data_logger = logging.getLogger('data')
    handler = logging.FileHandler('./data.log')
    fmt = logging.Formatter('%(asctime)s|%(message)s')
    handler.setFormatter(fmt)
    data_logger.addHandler(handler)
    data_logger.setLevel(logging.DEBUG)
    self.data_logger = data_logger
 
  def test_logger(self):
    self.data_logger.error("test_logger function")
    instance = Test()
    self.data_logger.error("test_logger output")
    instance.test_func()
 
 
def main():
  worker = Worker()
  worker.test_logger()
 
if __name__ == '__main__':
  main()
 

Problem 1: during the test, only test_logger function1 statements can be printed
Problem 2: obviously only the statement is printed in data_logger, but the related log also appears in the log of logger.

Problem 1 solution:

Debugging the script with the python-m pdb logger.py statement found that, after executing the instance = Test() statement, By using the print '\n'.join(['%s:%s' % item '] data_logger.items ()) debugging statement, the data_logger's disable property value is changed from 0 to True, and the corresponding logger properties are also changed. This change caused the logger object to stop logging. Refer to the relevant manual of python logging module and find that "The fileConfig() function takes a default parameter, disable_existing_loggers, which defaults to True for reasons compatibility This may or may be what you want, since it will cause any existing before fileConfig() to disabled unless they are explicitly in the configuration. "that is, calling the fileconfig() function disables all logger that existed before. In python 2.7, the fileConfig() function adds a parameter, logging.config.fileConfig (fname, defaults=None, disable_existing_loggers=True). disable_existing_loggers can be explicitly set to FALSE to avoid disabling the original logger. The problem can be solved by changing the logging.config.fileConfig function in the Test class above to logging.config.fileConfig ("./ logger.conf ", disable_existing_loggers=0). However, since this code is located in the same program, it can directly refer to the same logger with the logging.getLogger (LOGGOR_NAME) function, instead of calling the logging.config.fileConfig function to reload it once.

Problem 2 solution:

The logger object has a property propagate. If this property is True, the output information will be pushed to all the logger of the logger. The handlers corresponding to the logger will print the received information into the associated log. The root logger properties are configured in the logger.conf configuration file. This root logger is the default logger log.

The revised version is as follows:

File: logger conf


 
[formatters]
keys=default, data
 
[formatter_default]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
class=logging.Formatter
 
[formatter_data]
format=%(asctime)s|%(message)s
class=logging.Formatter
 
[handlers]
keys=console, error_file, data_file
 
[handler_console]
class=logging.StreamHandler
formatter=default
args=tuple()
 
[handler_error_file]
class=logging.FileHandler
level=INFO
formatter=default
args=("logger.log", "a")
 
[handler_data_file]
class=logging.FileHandler
level=INFO
formatter=data
args=("data_new.log", "a")
 
[loggers]
keys=root, data
 
[logger_root]
level=DEBUG
handlers=console,error_file
 
[logger_data]
level=DEBUG
handlers=data_file
qualname=data
propagate=0
 

File: logger py


 
#!/bin/env python
 
import logging
from logging.config import logging
 
class Test(object):
  """docstring for Test"""
  def __init__(self):
    self.logger = logging.getLogger(__name__)
 
  def test_func(self):
    self.logger.error('test_func function')
 
class Worker(object):
  """docstring for Worker"""
  def __init__(self):
    logging.config.fileConfig("logger.conf")
    self.logger = logging.getLogger(__name__)
    self.data_logger = logging.getLogger('data')
 
  def test_logger(self):
    self.data_logger.error("test_logger function")
    instance = Test()
    self.data_logger.error("test_logger output")
    instance.test_func()
 
 
def main():
  worker = Worker()
  worker.test_logger()
 
if __name__ == '__main__':
  main()


Related articles: