본문 바로가기
Python

[Python] logging

by llHoYall 2021. 10. 25.

Python has logging module.

It helps us to log the code flow.

Import logging module

import logging

logging.getLogger(__name__).addHandler(logging.NullHandler())

We can simply import the logging module and config it.

Use logging module (with Stack Trace)

import logging

def divide_by_zero():
    try:
        c = 3 / 0
    except Exception as e:
        logging.error("Exception ", exc_info=True)

divide_by_zero()
# ERROR:root:Exception 
# Traceback (most recent call last):
#   File "test.py", line 6, in divide_by_zero
#     c = 3 / 0
# ZeroDivisionError: division by zero

It is so easy to use.

We can also capture stack trace once exc_info parameter is set to True.

Config logging with Basic Configuration

import logging

logging.basicConfig(level=logging.DEBUG)

logging.critical("This is a critical logging")
logging.error("This is a error logging")
logging.warning("This is a warning logging")
logging.info("This is a info logging")
logging.debug("This is a debug logging")
# CRITICAL:root:This is a critical logging
# ERROR:root:This is a error logging
# WARNING:root:This is a warning logging
# INFO:root:This is a info logging
# DEBUG:root:This is a debug logging

The default logging level is a warning, but we can simply configure it with basicConfig().

logging.basicConfig(
    filename="logging.log",
    filemode="w",
    format="%(name)s - %(levelname)s - %(message)s",
)
# root - CRITICAL - This is a critical logging
# root - ERROR - This is a error logging
# root - WARNING - This is a warning logging

We can put a log to a file with formatting.

Config logging with Custom Logger

import logging

handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
handler.setFormatter(
    logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
)

logger = logging.getLogger("mylogger")
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)

logger.critical("This is a critical logging")
logger.error("This is a error logging")
logger.warning("This is a warning logging")
logger.info("This is a info logging")
logger.debug("This is a debug logging")
# 2021-10-25 20:47:19,757 - mylogger - CRITICAL - This is a critical logging
# 2021-10-25 20:47:19,757 - mylogger - ERROR - This is a error logging
# 2021-10-25 20:47:19,757 - mylogger - WARNING - This is a warning logging
# 2021-10-25 20:47:19,757 - mylogger - INFO - This is a info logging
# 2021-10-25 20:47:19,757 - mylogger - DEBUG - This is a debug logging

You can see the logger name that we set.

logger = logging.getLogger(__name__)
# 2021-10-25 20:53:31,362 - __main__ - CRITICAL - This is a critical logging
# 2021-10-25 20:53:31,362 - __main__ - ERROR - This is a error logging
# 2021-10-25 20:53:31,362 - __main__ - WARNING - This is a warning logging
# 2021-10-25 20:53:31,362 - __main__ - INFO - This is a info logging
# 2021-10-25 20:53:31,362 - __main__ - DEBUG - This is a debug logging

We can configure the logger name as the current module's name.

Config logging with Dictionary Configuration

import logging
from logging.config import dictConfig

logging_config = dict(
    version=1,
    formatters={"f": {"format": "%(asctime)s %(name)-12s %(levelname)-8s %(message)s"}},
    handlers={
        "h": {
            "class": "logging.StreamHandler",
            "formatter": "f",
            "level": logging.DEBUG,
        }
    },
    root={"handlers": ["h"], "level": logging.DEBUG},
)

dictConfig(logging_config)

logger = logging.getLogger()
logger.debug("This is debug logging")
#2021-10-24 22:23:16,521 root         DEBUG    This is debug logging

We can also config the logging module with dictionary configuration.

The available logging level is following:

Level Value
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0

Config logging with File Configuration

# logging.conf

[loggers]
keys=root,sampleLogger

[handlers]
keys=consoleHandler

[formatters]
keys=sampleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_sampleLogger]
level=DEBUG
handlers=consoleHandler
qualname=sampleLogger
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=sampleFormatter
args=(sys.stdout,)

[formatter_sampleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s

Create a configuration file we will use in INI file format.

import logging
import logging.config

logging.config.fileConfig(fname="logging.conf", disable_existing_loggers=False)

logger = logging.getLogger(__name__)
logger.debug("This is debug logging")
# 2021-10-24 22:35:31,098 - __main__ - DEBUG - This is debug logging

We can also use YAML file to configure.

# logging.yaml

version: 1
formatters:
  simple:
    format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
  console:
    class: logging.StreamHandler
    level: DEBUG
    formatter: simple
    stream: ext://sys.stdout
loggers:
  sampleLogger:
    level: DEBUG
    handlers: [console]
    propagate: no
root:
  level: DEBUG
  handlers: [console]

And use this.

import logging
import logging.config
import yaml

with open("logging.yaml", "r") as f:
    config = yaml.safe_load(f.read())
    logging.config.dictConfig(config)

logger = logging.getLogger(__name__)
logger.debug("This is debug logging")
# 2021-10-24 22:55:20,227 - __main__ - DEBUG - This is debug logging

'Python' 카테고리의 다른 글

[Python] Testing  (0) 2021.10.30
[Python] Debugging  (0) 2021.10.27
[Python] Docstring  (0) 2021.10.18
[Python] Running Python with Docker  (0) 2021.08.28
[PyQt6] Getting Started  (0) 2021.08.10

댓글