HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Logging module for use in other projects

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
loggingprojectsmoduleotherforuse

Problem

I'm trying to make a simple module I can paste into my various projects to provide basic logging capabilities. I'm hoping to become less dependent on print because:

  • Using logging will allow me to quickly enable and disable what's being logged



  • logging has built-in file and formatting utilities



  • The built-in levels of logging are helpful



Here's the log.py module:

import argparse
import logging
import sys

def parse_log_args(parser: argparse.ArgumentParser):
    default_level = 'INFO'
    parser.add_argument("-l", "--log", dest="loglevel",
                        choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
                        default=default_level,
                        help=f"Set the logging level (default: {default_level})",
                        type=str)

    parser.add_argument(
        '-lf', '--logfile',
        help="File for logging",
        dest="logfile",
        type=str
    )

    return parser

def conf_logging(logger: logging.Logger, loglevel: str, path=None):

    if loglevel.upper() not in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'):
        raise ValueError("Invalid logging level")

    if path is None:
        console_formatter = logging.Formatter('[%(levelname)s] %(message)s')
        handler = logging.StreamHandler(sys.stdout)
        handler.setFormatter(console_formatter)
    else:
        file_formatter = logging.Formatter(
            ('%(asctime)s [%(levelname)s] %(name)s.%(funcName)s'
             '@ L%(lineno)d\n  %(message)s'))
        handler = logging.FileHandler(path, encoding='utf-8')
        handler.setFormatter(file_formatter)

    l_name = logging.getLevelName(loglevel)
    handler.setLevel(l_name)
    logger.setLevel(l_name)

    logger.addHandler(handler)

    return logger


Here's an example of its usage:

```
import logging
import argparse
from log import parse_log_args, conf_logging

logger = logging.getLogger(__name__)

parser = argparse.ArgumentParser()

parser = parse_

Solution

It's more natural to say "--loglevel", ... than "--log", dest="loglevel", .... A log switch suggests that it takes an argument of a logfile output filename.

Not sure why you need dest for the logfile argument.

You're specifying type of str which is already the default, but maybe you did it to help with type annotations?

Raising "Invalid logging level" is maybe superfluous, better to let the underlying logging library deal with it. Looks like you're reaching across layers.

Naming your module log is perhaps a bit adventurous, as sometimes folks concisely write log.info() instead of logger.info().

In the example, I recommend deleting:

logger = logging.getLogger(__name__)


in favor of conf_logging(logging.getLogger(__name__), args.loglevel, args.logfile).
Perhaps you'd like to make it more convenient for callers, by defaulting loglevel, and letting a caller just pass in __name__ if that's all that is interesting.

Overall, it looks like a useful utility.

Code Snippets

logger = logging.getLogger(__name__)

Context

StackExchange Code Review Q#157903, answer score: 3

Revisions (0)

No revisions yet.