SoFunction
Updated on 2024-11-10

Examples and improvements to the python logging module

python prints the values of all attributes of an 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:< instance at 0x1d8bd88>
handlers:[< instance at 0x21bcc68>]
level:10
disabled:1   #Whether the current logger is valid or not, default is 0
manager:< instance at 0x1d8bea8>
propagate:0   #Whether to log this level
filters:[]
 

Some logs cannot be output

File:

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

File:

 
#!/bin/env python
 
import logging
from  import logging
 
class Test(object):
  """docstring for Test"""
  def __init__(self):
    ("")
     = (__name__)
 
  def test_func(self):
    ('test_func function')
 
class Worker(object):
  """docstring for Worker"""
  def __init__(self):
    ("")
     = (__name__)
 
    data_logger = ('data')
    handler = ('./')
    fmt = ('%(asctime)s|%(message)s')
    (fmt)
    data_logger.addHandler(handler)
    data_logger.setLevel()
    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 one statement of test_logger function can be printed out.
Problem 2: It is clear that the statement is only printed in data_logger, but the logger's log also shows the related log.

Problem 1 Solution:

Debugging the script with the python -m pdb statement reveals that after the execution of the instance = Test() statement, the debugging statement by printing '\n'.join(['%s:%s' % item for item in self.data_logger.__dict__.items()]) shows that The value of the data_logger's disable property changes from 0 to True, at which point the corresponding property of the logger undergoes the same change. This change causes the logger object to stop logging. Referring to the manual of the python logging module, I found that "The fileConfig() function takes a default parameter, disable_existing_loggers, which defaults to True for This may or may not be what you want, since it will cause any loggers existing before the fileConfig() call to be disabled unless they (or an ancestor of them) have been disabled. disabled unless they (or an ancestor) are explicitly named in the configuration." This may or may not be what you want, since it will cause any loggers existing before the fileConfig() call to be disabled unless they (or an ancestor) are explicitly named in the configuration. In python 2.7 the fileConfig() function takes a parameter, (fname, defaults=None, disable_existing_loggers=True), which allows you to explicitly set disable_existing_loggers to FALSE in order to avoid disabling the original logger is disabled. Change the function in the Test class in the above code to (". /", disable_existing_loggers=0) would solve the problem. However, in this code, since it is located in the same program, you can refer to the same logger directly with the (LOGGOR_NAME) function, so you don't have to call the function to reload it again.

Problem 2 Solution:

The logger object has a property propagate, if this property is True, the information to be output will be pushed to all the logger's superiors, and the handlers corresponding to these superiors will print the information received to the associated log. The configuration file is configured with the properties of the associated root logger, which is the default logger log.
 
The modifications are as follows:

File:

 
[formatters]
keys=default, data
 
[formatter_default]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
class=
 
[formatter_data]
format=%(asctime)s|%(message)s
class=
 
[handlers]
keys=console, error_file, data_file
 
[handler_console]
class=
formatter=default
args=tuple()
 
[handler_error_file]
class=
level=INFO
formatter=default
args=("", "a")
 
[handler_data_file]
class=
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:

 
#!/bin/env python
 
import logging
from  import logging
 
class Test(object):
  """docstring for Test"""
  def __init__(self):
     = (__name__)
 
  def test_func(self):
    ('test_func function')
 
class Worker(object):
  """docstring for Worker"""
  def __init__(self):
    ("")
     = (__name__)
    self.data_logger = ('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()