How do I change the format of a Python log message on a per-logger basis?

61,093

Solution 1

Try this

import logging

logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)
# create file handler that logs debug and higher level messages
fh = logging.FileHandler('spam.log')
fh.setLevel(logging.DEBUG)
# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
# create formatter and add it to the handlers
formatter = logging.Formatter(
    '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
fh.setFormatter(formatter)
# add the handlers to logger
logger.addHandler(ch)
logger.addHandler(fh)

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

See http://docs.python.org/howto/logging-cookbook.html#multiple-handlers-and-formatters for more information

Solution 2

You have to create or use an existing subclass of logging.Handler and call the setformatter() method of an instance thereof with an instance of a custom subclass of logger.Formatter. If you set the formatter for a handler that was already attached to the logger you want to modify the output of, you are fine, otherwise you have to retrieve a logger object with logging.getLogger() and call its addHandler() method with the instance of your handler class that you set the formatter on as the argument.

Share:
61,093
Ricardo Altamirano
Author by

Ricardo Altamirano

Originally from Nicaragua, educated in Edinburgh and the USA, and now living primarily in London. Useful questions and answers Stack Overflow Debugging CREATE TABLE statements Logging in Python Simple string formatting in Python Reference types in C# String compression in C# using Gzip Meta Stack Overflow Book recommendation questions Answering old questions with a solution in the comments IT Security Cryptographically secure random strings in PHP LaTeX Fitting a table on a page through rotation StackExchange Flair

Updated on August 13, 2020

Comments

  • Ricardo Altamirano
    Ricardo Altamirano over 3 years

    After reading the documentation on logging, I know I can use code like this to perform simple logging:

    import logging
    
    def main():
        logging.basicConfig(filename="messages.log",
                            level=logging.WARNING,
                            format='%(filename)s: '    
                                    '%(levelname)s: '
                                    '%(funcName)s(): '
                                    '%(lineno)d:\t'
                                    '%(message)s')
    
        logging.debug("Only for debug purposes\n")
        logging.shutdown()
    
    main()
    

    However, I realised I don't know how to change the format of log messages on a per-logger basis, since basicConfig is a module-level function. This code works for creating different loggers with different levels, names, etc. but is there a way to change the format of those log messages on a per-logger basis as well, in a way similar to basicConfig?

    import inspect
    import logging
    
    def function_logger(level=logging.DEBUG):
        function_name = inspect.stack()[1][3]
        logger = logging.getLogger(function_name)
        logger.setLevel(level)
        logger.addHandler(logging.FileHandler("{0}.log".format(function_name)))
        return logger
    
    def f1():
        f1_logger = function_logger()
        f1_logger.debug("f1 Debug message")
        f1_logger.warning("f1 Warning message")
        f1_logger.critical("f1 Critical message")
    
    def f2():
        f2_logger = function_logger(logging.WARNING)
        f2_logger.debug("f2 Debug message")
        f2_logger.warning("f2 Warning message")
        f2_logger.critical("f2 Critical message")
    
    def main():
        f1()
        f2()
        logging.shutdown()
    
    main()