Log levels

Built in methods for logging or a logging.Logger instance:

  • logging.debug
  • logging.info
  • logging.warning
  • logging.error
  • logging.critical

Note

Setting log level is not enough. You need to make sure to call basicConfig first or add handlers as on Configuration examples on page, otherwise it won’t work.

import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

# This message will get ignored.
logger.info("This is an info message from your application.")

Configuration

The default is to log WARNING level to stdout. You can specify a log level a output file as below.

Configure and use the library directly

Here is a simple config setup from the docs. Without using a logging.Logger instance.

import logging


logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.DEBUG)

logging.info("Message")

Configure and use a logger variable

Make a logger (as a global variable or class variable) and use it.

Here using basicConfig which affects all loggers including those for external packages.

import logging

# Set up your application's logger.
logger = logging.getLogger(__name__)
logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.INFO)

# Call the instance.
logger.info("Info message")
logger.debug("Debug message")

# Change the log level.
logger.setLevel(logging.INFO)
logger.info("Info message")
logger.debug("Debug message")

Using handlers for a specific logger, without basicConfig.

import logging

# Set up your application's logger.
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

# Create a console handler.
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)

# Create a formatter.
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
console_handler.setFormatter(formatter)

logger.addHandler(console_handler)

# Prevent external packages from logging noisly at the info level.
logging.getLogger().setLevel(logging.WARNING)

# Example usage.
logger.info("This is an info message from your application.")
logger.warning("This is a warning message from your application.")

Note if you run the above multiple times, you’ll log the same message multiple times. So check the handlers:

def initialize_logger(name: str) -> logging.Logger:
    logger = logging.getLogger(name)
    logger.setLevel(logging.INFO)

    if not logger.hasHandlers():
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)

        formatter = logging.Formatter(
            "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
        )
        console_handler.setFormatter(formatter)

        logger.addHandler(console_handler)

        # Prevent external packages from logging noisily at the info level.
        logging.getLogger().setLevel(logging.WARNING)

    return logger

# Use an import like this from another module:
# from utils import initialize_logger

logger = initialize_logger(__name__)

logger.info("This is an info message from your application.")
logger.warning("This is a warning message from your application.")

Variable substitution

Pass literal values to logging message.

logging.info("Hello %s, my name is %", "world", "Joe")

Or variables.

name = 'world'
logging.info("Hello %s", name)

Using extra keyword, based on the docs.

FORMAT = '%(asctime)s %(clientip)-15s %(user)-8s %(message)s'
logging.basicConfig(format=FORMAT)
logger = logging.getLogger('tcpserver')

d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
logger.warning('Protocol problem: %s', 'connection reset', extra=d)

Would print something like:

2006-02-08 22:20:02,165 192.168.0.1 fbloggs  Protocol problem: connection reset

Built-in variables

See LogRecord attributes in the docs.

Including some like:

  • %(filename)s - name of the current file
  • %(funcName)s - name of the function in current scope
  • %(thread)d - thread ID if available
  • %(threadName)s - thread name if available

Levels

Basic

logger.debug(msg)
logger.info(msg)
logger.error(msg)

Add error trace

logger.exception(msg)

Equivalent to:

logger.error(msg, exc_info=True)

This will log the stack trace of the current error, so you don’t have to add str(e) to your message.

try:
    # ...
except Exception as e:
    logger.exception(msg)