How to insert newline in python logging?

logging, newline, python, python-logging

Solution

I have two solutions, the first is very easy, but the output is not very clean. The second method will produce the exact output you want, but it is a little more involved.

Method 1

To produce a blank line, just log an empty string with a new line:

import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
logging.info('hello')
logging.info('\n')
logging.warning('new hello')

The output will have an empty info line, which is not very clean:

16:07:26 INFO hello 16:07:26 INFO

16:07:26 WARNING new hello

Method 2

In this method, I created two different handlers. The `console_handler` which I use most of the time. When I need a new line, I switch to a second handler, `blank_handler`.

import logging
import types

def log_newline(self, how_many_lines=1):
    # Switch handler, output a blank line
    self.removeHandler(self.console_handler)
    self.addHandler(self.blank_handler)
    for i in range(how_many_lines):
        self.info('')

    # Switch back
    self.removeHandler(self.blank_handler)
    self.addHandler(self.console_handler)

def create_logger():
    # Create a handler
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.DEBUG)
    console_handler.setFormatter(logging.Formatter(fmt="%(name)s %(levelname)-8s: %(message)s"))

    # Create a "blank line" handler
    blank_handler = logging.StreamHandler()
    blank_handler.setLevel(logging.DEBUG)
    blank_handler.setFormatter(logging.Formatter(fmt=''))

    # Create a logger, with the previously-defined handler
    logger = logging.getLogger('logging_test')
    logger.setLevel(logging.DEBUG)
    logger.addHandler(console_handler)

    # Save some data and add a method to logger object
    logger.console_handler = console_handler
    logger.blank_handler = blank_handler
    logger.newline = types.MethodType(log_newline, logger)

    return logger

if __name__ == '__main__':
    logger = create_logger()
    logger.info('Start reading database')
    logger.info('Updating records ...')
    logger.newline()
    logger.info('Finish updating records')

The output is what you want to see:

logging_test INFO    : Start reading database
logging_test INFO    : Updating records ...

logging_test INFO    : Finish updating records

Discussion

- If you can put up with the less-than-perfect output, method 1 is the way to go. It has the advantage of being simple, least amount of effort.

- The second method does the job correctly, but it is a little involved. It creates two different handlers and switch them in order to achieve your goal.

- Another disadvantage of using method 2 is you have to change your code by searching for `logging` and replacing them with `logger`. You must take care replacing only relevant parts and leave such text as `logging.DEBUG` in tact.

Problem

``` import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S') logging.info('hello') logging.warning('\n new hello') ``` 11:15:01 INFO hello 11:16:49 WARNING new hello Because the log is crowded, I want to explicitly insert a newline before `asctime` and `levelname`. Is this possible without modifying `format`? I looked into `logging` module and googled a bit and could not find a viable way.

Original source