I want to do something which I thought is simple.
Actually with the python logging module, I am interested logging everything on the command line at the level given from the command line arguments, and log to file to a fixed DEBUG level.
Creating two different loggers with different levels doesn't work, but setting the levels of two different handlers both added to the root logger doesn't work either, so any idea about how I should actually do it? (reading on other links the second approach should work, so am I doing something else stupid?)
This is the code which sets up my logging system at the moment:
class LoggerSetup(object):
"""Setup the different logger objects
"""
def __init__(self):
self.root_logger = logging.getLogger()
self.shell_hdlr = logging.StreamHandler()
#TODO: add another logging handler which stores to a temporary file
#which should be cleaned up later
def setup_shell_logger(self, log_level):
self.root_logger.setLevel(LOG_LEVELS[log_level])
# in this way the root logger is not set but the handlers are set
self.shell_hdlr = logging.StreamHandler()
self.shell_hdlr.setLevel(LOG_LEVELS[log_level])
self.shell_hdlr.setFormatter(StarFormatter())
#FIXME: add the support for regular expression exclusion too
self.root_logger.addHandler(self.shell_hdlr)
def setup_log_include(self, log_include):
"""Set up the filter to include log messages
"""
if log_include:
incl = FilterInclude(log_include)
self.shell_hdlr.addFilter(incl)
def setup_log_exclude(self, log_exclude):
"""Set up the filters to exclude log messages
"""
if log_exclude:
excl = FilterExclude(log_exclude)
self.shell_hdlr.addFilter(excl)
def setup_file_logging(self):
"""Set up the file logger, which always logs in DEBUG mode
even if the top level logger is set to another level
"""
#XXX: not working, one possible way to make it work is to create
#only one log, and different handler/filters to make to handle all
#the different outputs
file_handler = logging.FileHandler(LOG_FILENAME)
# the file logging is always in debug mode
file_handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s - %(asctime)s')
file_handler.setFormatter(formatter)
self.root_logger.addHandler(file_handler)
The default level is WARNING , which means that only events of this level and above will be tracked, unless the logging package is configured to do otherwise. Events that are tracked can be handled in different ways. The simplest way of handling tracked events is to print them to the console.
Logging is a means of tracking events that happen when some software runs. Logging is important for software developing, debugging, and running. If you don't have any logging record and your program crashes, there are very few chances that you detect the cause of the problem.
This is something I'm using with all of my Python command-line apps. It's a little verbose, but you should be able to get a logger that accepts an optional argument to create a console logger at any level, irrespective of what's being logged to the file:
#!/usr/bin/env python
import logging
from argparse import ArgumentParser
COMPANY_LOGGER = 'COMPANY.Python.Logger'
CONSL_LEVEL_RANGE = range(0, 51)
LOG_FILE = 'company.log'
FORMAT_STR = '%(asctime)s %(levelname)s %(message)s'
parser = ArgumentParser()
parser.add_argument('-c', '--console-log', metavar='ARG',
type=int, choices=range(0, 51),
action='store', dest='console_log',
default=None,
help='Adds a console logger for the level specified in the range 1..50')
args = parser.parse_args()
# Create logger
logger = logging.getLogger(COMPANY_LOGGER)
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(FORMAT_STR)
# Add FileHandler and only log WARNING and higher
fh = logging.FileHandler(LOG_FILE)
fh.name = 'File Logger'
fh.level = logging.WARNING
fh.formatter = formatter
logger.addHandler(fh)
# Add optional ConsoleHandler
if args.console_log:
ch = logging.StreamHandler()
ch.name = 'Console Logger'
ch.level = args.console_log
ch.formatter = formatter
logger.addHandler(ch)
logger.debug('DEBUG')
logger.info('INFO')
logger.warning('WARNING')
logger.critical('CRITICAL')
Whenrun from the command line we can see the differences in logged levels.
-c1
equates to "DEBUG and higher" (the most verbose), but company.log is still only logging WARNING and higher:
~ zacharyyoung$ ./so.py -c1
2012-01-12 08:59:50,086 DEBUG DEBUG
2012-01-12 08:59:50,086 INFO INFO
2012-01-12 08:59:50,087 WARNING WARNING
2012-01-12 08:59:50,087 CRITICAL CRITICAL
~ zacharyyoung$ cat company.log
2012-01-12 08:59:50,087 WARNING WARNING
2012-01-12 08:59:50,087 CRITICAL CRITICAL
-c20
equates to INFO:
~ zacharyyoung$ ./so.py -c20
2012-01-12 09:00:09,393 INFO INFO
2012-01-12 09:00:09,393 WARNING WARNING
2012-01-12 09:00:09,393 CRITICAL CRITICAL
~ zacharyyoung$ cat company.log
2012-01-12 08:59:50,087 WARNING WARNING
2012-01-12 08:59:50,087 CRITICAL CRITICAL
2012-01-12 09:00:09,393 WARNING WARNING
2012-01-12 09:00:09,393 CRITICAL CRITICAL
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With