10
\$\begingroup\$

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_log_args(parser)
args = parser.parse_args()
logger = conf_logging(logger, args.loglevel, args.logfile)
logger.debug("What")
logger.info("okay")

Which can be called as follows:

> python basic.py --log INFO
[INFO] okay
> python basic.py --log DEBUG
[DEBUG] What
[INFO] okay

I'm not super familiar with the logging module, so I was a little surprised I had to have to set the logging lever for both the logger and the handler. Is there a better, more explicit way of writing this?

asked Mar 16, 2017 at 8:56
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Please don't modify your code. After getting an answer you are not allowed to change your code anymore. This is to ensure that answers do not get invalidated and have to hit a moving target. If you have changed your code you can either post it as an answer (if it would constitute a code review) or ask a new question with your changed code (linking back to this one as reference). Refer to this post for more information. \$\endgroup\$ Commented May 1, 2019 at 17:58
  • \$\begingroup\$ @SᴀᴍOnᴇᴌᴀ understood. I will make sure not to change my code. \$\endgroup\$ Commented May 1, 2019 at 18:00

1 Answer 1

3
\$\begingroup\$

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.

answered Sep 4, 2017 at 3:13
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.