Basic Python

Logger, Handler, Filter, Formatter

Naranjito 2023. 12. 8. 20:35
  • logging

Logging is a means of tracking events that happen when some software runs. The software’s developer adds logging calls to their code to indicate that certain events have occurred. An event is described by a descriptive message which can optionally contain variable data (i.e. data that is potentially different for each occurrence of the event). 

 

  • Log Levels

The log has a level one of these below.

Level When it’s used
DEBUG Detailed information,
typically of interest only when diagnosing problems.
INFO Confirmation that things are working as expected.
WARNING An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’).
The software is still working as expected.
ERROR Due to a more serious problem,
the software has not been able to perform some function.
CRITICAL A serious error,
indicating that the program itself may be unable to continue running.

 

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.


Since I set the logger lever to WARNING, only logs with a WARNING or higher lever are selected and recorded.

 

example 1.

 

logging.warning('watch out')
logging.info('watch out watch out')
>>>
WARNING:root:watch out

 

example 2.

logging.basicConfig(level=logging.WARNING)
logging.debug('this message should go to the log file')
logging.info('so should this')
logging.warning('and this, too')
logging.error('and non askii stuff, too, like Øresund and Malmö')
logging.critical('critical error')

>>>
WARNING:root:and this, too
ERROR:root:and non askii stuff, too, like Øresund and Malmö
CRITICAL:root:critical error

  • basicConfig

If the location where the log will be stored and the log level threshold to be stored are set here, and subsequent log events are filtered and stored in the log file.

If you do not set this function, it is automatically called when debug, info, etc are called.

Only the first call is valid, and subsequent calls do not function.

 

  • Logging to a file

The messages from successive runs are appended to the file example.log.

logging.basicConfig(filename="example.log", level=logging.WARNING)

 

If you want each run to start afresh, not remembering the messages from earlier runs, you can specify the filemode argument,

filemode='w'

The output will be the same as before, but the log file is no longer appended to, so the messages from earlier runs are lost.

logging.basicConfig(filename="example.log", filemod="w", level=logging.WARNING)

 

  • Hierarchical Structure

It conceptually arranged in a namespace hierarchy using dots (periods) as separators. The root of the hierarchy of loggers is called the root logger.

For example, 

postprocess is a sub-module of data,

skeleton is a sub-module of postprocess.

data.postprocess.skeleton

 


1. Logger

It exposes the interface that application code directly uses from the program such as warning, info, setLevel.

 

  • set up the Logger
logger = logging.getLogger(__name__)

 

If you call the functions debug()info()warning()error() and critical(), they will check to see if no destination is set, and if one is not set, they will set a destination of the console (sys.stderr) and a default format for the displayed message before delegating to the root logger to do the actual message output.

 

  • setLevel

The Logger is defined in 'skeleton' which is a sub module of 'postprocessor' module, and the record threshold severity is set to the WARNING level.

logger = logging.getLogger("postprocessor.skeleton")
logger.setLevel(logging.WARNING)

 

  • effective level

If a level is not explicitly set on a logger, the level of its parent is used instead. If the parent has no explicit level set, its parent is examined, and so on - all ancestors are searched until an explicitly set level is found. The root logger always has an explicit level set (WARNING by default). When deciding whether to process an event, the effective level of the logger is used to determine whether the event is passed to the logger’s handlers.

logger = logging.getLogger("postprocessor")
logger.setLevel(logging.DEBUG)

logger = logging.getLogger("postprocessor.skeleton")
logger.setLevel(logging.NOTSET)

print(logger.getEffectiveLevel() == logging.DEBUG)
>>> True

 

2. Handler

It sends the log records (created by loggers) to the appropriate destination such as a specific file or console output, or a network socket. By default, no destination is set for any logging messages.

 

Handler objects are responsible for dispatching the appropriate log messages (based on the log messages’ severity) to the handler’s specified destinationLogger objects can add zero or more handler objects to themselves with an addHandler() method. 

 

  • StreamHandler

It sends the message to the consol.

logger = logging.getLogger("skeleton")
stream_handler = logging.StreamHandler()
logger.addHandler(stream_handler)

 

  • FileHandler

It sends the message to the disk file.

logger = logging.getLogger("skeleton")
file_handler = logging.FileHandler()
logger.addHandler(file_handler)

 

3. Formatter

It transforms the layout of log records into the human-readable form.

It configure the final order, structure, and contents of the log message.

 

formatter=logging.Formatter("%(asctime)s %(levelname)s:%(message)s")
handler = logging.StreamHandler()
handler.setFormatter(formatter)

logger.addHandler(handler)
logger.info("Is working well?")
>>>
2023-12-08 20:14:27,582 INFO:Is working well?

 

 


4. Filter

It provides a finer grained facility for determining which log records to output.

It allows filtering by specific logger name. If this feature is used, messages sent to the named logger and its children are allowed through the filter, and all others dropped.

 

- Set up the Logger

logger_preprocess = logging.getLogger("preprocess")
logger_postprocess = logging.getLogger("postprocess")

 

- Set up the Formatter, Filter

formatter = logging.Formatter("%(asctime)s %(levelname)s:%(message)s")
filter = logging.Filter("postprocess")

 

- Set up the Handler

handler = logging.StreamHandler()
handler.setFormatter(formatter)
handler.addFilter(filter)

 

 

- Add the Handler

logger_preprocess.addHandler(handler)
logger_postprocess.addHandler(handler)

 

The two loggers use the same handler, but the 'logger_preprocess' are not processed as a result because the filter setting is to process only events under the postprocess.

logger_preprocess.critical("Critical from preprocess.")
logger_postprocess.critical("Critical from postprocess.")
>>>
2022-04-23 18:23:58,185 CRITICAL:Critical from postprocess.

 

https://jh-bk.tistory.com/40

https://docs.python.org/3/howto/logging.html#logging-basic-tutorial

'Basic Python' 카테고리의 다른 글

cv2.imread  (0) 2024.02.28
argparse  (0) 2023.12.13
str VS repr  (0) 2023.11.16
getattr  (0) 2023.11.15
sort VS sorted  (0) 2023.11.10