The example mainly solves the problem of changing the log storage location by passing in the log file parameters. If you need it, you can refer to the simple version of logging. config, which supports general configuration through the config file.
Another better way is to use the logging. config. fileConfig (log_config_file) method to read in and modify the handler method.
The Code is as follows:
"""
Project trace system
"""
Import sys
Import ConfigParser
Import logging
Import logging. config
Import warnings
If _ name _ = "_ main __":
Log_config_file = "log. conf"
Log_data_file = "logs/run. log"
LEVEL_dic = {
"DEBUG": logging. DEBUG,
"INFO": logging. INFO,
"WARNING": logging. WARNING,
"ERROR": logging. ERROR,
"CRITICAL": logging. CRITICAL
}
Class LogConfig (object ):
Def _ init _ (self, log_config_file, log_data_file = None ):
Self. log_config_file = log_config_file
Self. log_data_file = log_data_file # for self app
Self. log_config = ConfigParser. RawConfigParser ()
Self. log_config.read (self. log_config_file)
Self. logger_prefix = "logger _"
Self. handler_prefix = "handler _"
Self. formatter_prefix = "formatter _"
Self. _ check_section ()
Self. _ parse_option ()
Def _ check_section (self ):
# Check logger
Self. _ check_logger ()
# Check handler
Self. _ check_handler ()
# Check formatter
Self. _ check_formatter ()
Def _ parse_option (self ):
# Parse formatter option
For formatter, formatter_info in self. formatters. items ():
Section_name = formatter_info ["section_name"]
F = self. log_config.get (section_name, "format ")
Datefmt = self. log_config.get (section_name, "datefmt ")
Self. formatters [formatter] ["value"] = logging. Formatter (f, datefmt)
# Parse handlers
For handler, handler_info in self. handlers. items ():
Section_name = handler_info ["section_name"]
Handler_class = self. log_config.get (section_name, "class ")
Handler_str = self. log_config.get (section_name, "args ")
Handler_args = eval (self. log_config.get (section_name, "args "))
Level = self. log_config.get (section_name, "level ")
Formatter = self. log_config.get (section_name, "formatter ")
_ Handler = eval ("logging." + handler_class)
# Only FileHandler has file path paramter.
If isinstance (_ handler, logging. FileHandler ):
If self. log_data_file:
Handler_args [0] = self. log_data_file
Else:
Warnings. warn ("fileHandler found, but log data file is not specified ")
Self. handlers [handler] ["value"] = _ handler (* handler_args)
Self. handlers [handler] ["value"]. setLevel (
LEVEL_dic.get (level. upper (), LEVEL_dic ["INFO"])
Self. handlers [handler] ["value"]. setFormatter (
Self. formatters [formatter] ["value"])
# Parse logger
For logger, logger_info in self. loggers. items ():
Section_name = logger_info ["section_name"]
Self. _ parse_logger (logger, section_name)
Def _ parse_logger (self, logger_name, section_name ):
"""
"""
Tuple_items = self. log_config.items (section_name)
Logger = logging. getLogger (logger_name)
For k, v in tuple_items:
If k = "handlers ":
Handlers = filter (None, [h. strip () for h in v. split (",")])
For h in handlers:
Logger. addHandler (self. handlers [h] ["value"])
If k = "level ":
Logger. setLevel (LEVEL_dic.get (v, LEVEL_dic ["INFO"])
If k = "propagate" and v:
Logger. propagate = int (v)
# Here other attributes cocould be added. TODO
Self. loggers [logger_name] ['value'] = logger
Def _ check_logger (self ):
_ Loggers = self. log_config.get ("loggers", "keys"). split (",")
Self. loggers = {}
For logger in _ loggers:
Logger = logger. strip ()
If logger:
Logger_section_name = self. logger_prefix + logger
If not self. log_config.has_section (logger_section_name ):
Raise Exception (
"ERROR: no logger section name: {0}". format (logger_section_name ))
Self. loggers. setdefault (logger ,{})
Self. loggers [logger] ["section_name"] = logger_section_name
If not self. loggers:
Raise Exception (
"ERROR: No logger keys in {0}". format (self. log_config_file ))
Def _ check_handler (self ):
_ Handlers = self. log_config.get ("handlers", "keys"). split (",")
Self. handlers = {}
For handler in _ handlers:
Handler = handler. strip ()
If handler:
Handler_section_name = self. handler_prefix + handler
If not self. log_config.has_section (handler_section_name ):
Raise Exception ("ERROR: no handler section name: {0}". format (handler_section_name ))
Self. handlers. setdefault (handler ,{})
Self. handlers [handler] ["section_name"] = handler_section_name
If not self. handlers:
Raise Exception ("ERROR: No handler keys in {0}". format (self. log_config_file ))
Def _ check_formatter (self ):
_ Formatters = self. log_config.get ("formatters", "keys"). split (",")
Self. formatters = {}
For formatter in _ formatters:
Formatter = formatter. strip ()
If formatter:
Formatter_section_name = self. formatter_prefix + formatter
If not self. log_config.has_section (formatter_section_name ):
Raise Exception ("ERROR: no formatter section name: {0}". format (formatter_section_name ))
Self. formatters. setdefault (formatter ,{})
Self. formatters [formatter] ["section_name"] = formatter_section_name
If not self. formatters:
Raise Exception ("ERROR: No formatter keys in {0}". format (self. log_config_file ))
Def getLogger (self, logger_name = "root "):
Return self. loggers [logger_name] ['value']
Class Trace (object ):
Def _ init _ (self, log_config_file, log_key = "root", log_data_file = None ):
Self. log_config_file = log_config_file
Self. log_data_file = log_data_file
Self. log_key = log_key
Log = LogConfig (self. log_config_file, self. log_data_file)
Self. logger = Log. getLogger (self. log_key)
Def info (self, key, info ):
Self.logger.info ("[{0}]: {1}". format (key, info ))
Def error (self, key, err_info ):
Self. logger. error ("[{0}]: {1}". format (key, err_info ))
Def warn (self, key, warn_info ):
Self. logger. warn ("[{0}]: {1}". format (key, warn_info ))
Def test ():
Log_key = "root"
T = Trace (log_config_file, log_key, log_data_file)
T.info ("test trace", "OK ")
If _ name _ = "_ main __":
Test ()
Log. conf
The Code is as follows:
[Loggers]
Keys = root, debug
[Handlers]
Keys = lelehandler, timedRotatingFileHandler
[Formatters]
Keys = simpleFormatter
[Logger_root]
Level = DEBUG
Handlers = lelehandler, timedRotatingFileHandler
[Logger_debug]
Level = DEBUG
Handlers = consoleHandler
Propagate = 0
[Handler_consoleHandler]
Class = StreamHandler
Level = DEBUG
Formatter = simpleFormatter
Args = (sys. stdout ,)
[Handler_timedRotatingFileHandler]
Class = handlers. TimedRotatingFileHandler
Level = DEBUG
Formatter = simpleFormatter
Args = ("./run. log", 'midnight ', 1, 10)
[Formatter_simpleFormatter]
Format = [% (asctime) s] [% (levelname) s] [% (process) d: % (thread) d] [% (filename) s: % (lineno) d]: % (message) s
Datefmt = % Y-% m-% d % H: % M: % S