3

I am trying to make it easy to debug my code as my project grows. I hate adding and removing print or debug statements (why not just leave them in?) The problem is the output becomes messy to read. I am trying to be able to set up logging in different files and levels so I can turn it on or off via the logging.conf configuration file.

Here is my code:

import logging.config logging.config.fileConfig('logging.conf') if __name__ == "__main__": one = logging.getLogger("oneLogger") two = logging.getLogger("twoLogger") one.debug("debug on one") one.info("info on one") one.warn("warn on one") one.error("error on one") one.critical("critical on one") two.debug("debug on two") two.info("info on two") two.warn("warn on two") two.error("error on two") two.critical("critical on two") 

Here is my logging.conf file:

[loggers] keys=root,oneLogger, twoLogger [handlers] keys=rootHandler, oneHandler, twoHandler [formatters] keys=rootFormatter,oneFormatter, twoFormatter [logger_root] level=DEBUG handlers=rootHandler [logger_oneLogger] level=DEBUG handlers=oneHandler qualname=main propagate=1 [logger_twoLogger] level=CRITICAL handlers=twoHandler qualname=main propagate=1 [handler_rootHandler] class=StreamHandler formatter=rootFormatter args=(sys.stdout,) [handler_oneHandler] class=StreamHandler formatter=oneFormatter args=(sys.stdout,) [handler_twoHandler] class=StreamHandler formatter=twoFormatter args=(sys.stdout,) [formatter_rootFormatter] format=Root: %(asctime)s - %(name)s - %(levelname)s - %(message)s datefmt= [formatter_oneFormatter] format=One: %(asctime)s - %(name)s - %(levelname)s - %(message)s datefmt= [formatter_twoFormatter] format=Two: %(asctime)s - %(name)s - %(levelname)s - %(message)s datefmt= 

I would have expected this output:

One: 2016-12-22 16:36:32,414 - one - DEBUG - debug on one One: 2016-12-22 16:36:32,414 - one - INFO - info on one One: 2016-12-22 16:36:32,415 - one - WARNING - warn on one One: 2016-12-22 16:36:32,417 - one - ERROR - error on one One: 2016-12-22 16:36:32,417 - one - CRITICAL - critical on one Two: 2016-12-22 16:36:32,421 - two - CRITICAL - critical on two 

Instead I got this:

Root: 2016-12-22 16:36:32,414 - one - DEBUG - debug on one Root: 2016-12-22 16:36:32,414 - one - INFO - info on one Root: 2016-12-22 16:36:32,415 - one - WARNING - warn on one Root: 2016-12-22 16:36:32,417 - one - ERROR - error on one Root: 2016-12-22 16:36:32,417 - one - CRITICAL - critical on one Root: 2016-12-22 16:36:32,418 - two - DEBUG - debug on two Root: 2016-12-22 16:36:32,418 - two - INFO - info on two Root: 2016-12-22 16:36:32,420 - two - WARNING - warn on two Root: 2016-12-22 16:36:32,421 - two - ERROR - error on two Root: 2016-12-22 16:36:32,421 - two - CRITICAL - critical on two 

I was expecting that logger two would be limited to only CRITICAL logs and logger one would accept all logs. Instead, I was surprised to see that the root logger handled ALL of the logs.

What am I doing/assuming wrong?

1 Answer 1

4

Got it. It seems that "qualname" is what I was looking for and NOT the name of the logger itself:

Here is my code:

import logging.config logging.config.fileConfig('logging.conf') if __name__ == "__main__": one = logging.getLogger("one.oneLogger") one.debug("debug on one") one.info("info on one") one.warn("warn on one") one.error("error on one") one.critical("critical on one") two = logging.getLogger("two") two.debug("debug on two") two.info("info on two") two.warn("warn on two") two.error("error on two") two.critical("critical on two") root = logging.getLogger() root.debug("debug on root") root.info("info on root") root.warn("warn on root") root.error("error on root") root.critical("critical on root") 

Here is my logging.conf file:

[loggers] keys:root,twoLogger,oneLogger [handlers] keys:rootHandler,oneHandler,twoHandler [formatters] keys:rootFormatter,oneFormatter,twoFormatter [logger_root] level:DEBUG handlers:rootHandler [logger_oneLogger] level:WARN handlers:oneHandler qualname:one propagate:0 [logger_twoLogger] level:CRITICAL handlers:twoHandler qualname:two propagate:0 [handler_rootHandler] class:StreamHandler formatter:rootFormatter args:(sys.stdout,) [handler_oneHandler] class:StreamHandler formatter:oneFormatter args:(sys.stdout,) [handler_twoHandler] class:StreamHandler formatter:twoFormatter args:(sys.stdout,) [formatter_rootFormatter] format:Root: %(asctime)s - %(name)s - %(levelname)s - %(message)s datefmt: [formatter_oneFormatter] format:One: %(asctime)s - %(name)s - %(levelname)s - %(message)s datefmt: [formatter_twoFormatter] format:Two: %(asctime)s - %(name)s - %(levelname)s - %(message)s datefmt: 

Here is my output:

One: 2016-12-24 12:46:14,244 - one.oneLogger - WARNING - warn on one One: 2016-12-24 12:46:14,246 - one.oneLogger - ERROR - error on one One: 2016-12-24 12:46:14,246 - one.oneLogger - CRITICAL - critical on one Two: 2016-12-24 12:46:14,247 - two.twoLogger - CRITICAL - critical on two Root: 2016-12-24 12:46:14,249 - root - DEBUG - debug on root Root: 2016-12-24 12:46:14,249 - root - INFO - info on root Root: 2016-12-24 12:46:14,250 - root - WARNING - warn on root Root: 2016-12-24 12:46:14,250 - root - ERROR - error on root Root: 2016-12-24 12:46:14,252 - root - CRITICAL - critical on root 
Sign up to request clarification or add additional context in comments.

2 Comments

What's the difference between calling logging.getLogger("one.oneLogger") and logging.getLogger("two")?
In the logging.conf file, I have "oneHandler" (qualname is"one") setup to log warning messages and above and "twoLogger" (qualname is"two") setup to log only critical messages Any logger that matches the root name of the logger in the conf file will be used. If I were to add another logger in the conf file that had a a qualname of "one.oneLogger" the logging subsystem would match it before "one" and use its level (and handler(s))

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.