書き捨て以上、製品以下くらいの、自分用・社内用ツール的なスクリプトをPythonで作るとき、つい適当にしがちなログ処理を上品に実装するためのメモ。
#!/usr/bin/env python3
from logging import getLogger
logger = getLogger(__name__)
del getLogger
def _main():
from argparse import ArgumentParser
parser = ArgumentParser()
# configure arguments here
set_logging_arguments(parser)
args = parser.parse_args()
init_logging(args)
log_environment_info(args)
logger.debug('This is debug message.')
logger.info('This is info message.')
logger.warning('This is warning message.')
logger.error('This is error message.')
logger.critical('This is critical message.')
def set_logging_arguments(parser):
q = parser.add_argument_group('logging arguments')
q.add_argument('--verbose', '-v', action='count', default=0, help='increase log level')
q.add_argument('--quiet', '-q', action='count', default=0, help='decrease log level')
q.add_argument('--logfile', help='dump all logs to file')
def init_logging(args):
from logging import getLogger, StreamHandler, FileHandler, Formatter, NOTSET, WARNING, CRITICAL
rootlogger = getLogger()
rootlogger.setLevel(NOTSET)
handler = StreamHandler()
# https://docs.python.org/3/library/logging.html?highlight=notset#logging-levels
handler.setLevel(sorted([NOTSET, WARNING+(args.quiet-args.verbose)*10, CRITICAL])[1])
rootlogger.addHandler(handler)
if args.logfile:
handler = FileHandler(args.logfile)
handler.setLevel(NOTSET)
# https://docs.python.org/3/library/logging.html?highlight=notset#logrecord-attributes
handler.setFormatter(Formatter('%(asctime)s: %(name)s: %(levelname)s: %(message)s'))
rootlogger.addHandler(handler)
def log_environment_info(args, *, logger=logger, envvars=True):
import sys, os
logger.debug(f'python executable: {sys.executable}')
logger.debug(f'python version: {sys.version}')
logger.debug(f'working directory: {os.getcwd()}')
logger.debug(f'command line: {" ".join(map(repr,sys.argv))}')
logger.debug(f'arguments:')
for k in sorted(vars(args).keys()):
logger.debug(f' {k}: {getattr(args, k)!r}')
if envvars:
logger.debug(f'environment variables:')
for k, v in sorted(os.environ.items()):
logger.debug(f' {k}: {v!r}')
if __name__ == '__main__':
_main()
コマンドラインに、-q
又は-v
オプションを必要な個数付けることで、標準エラー出力に出すログの量を変えられるようにしている。
--logfile
を指定すれば実行時の環境情報も含めて全てのログをファイルにダンプできる。環境変数までは要らない、という場合はenvvars=False
としてやる。
ログ設定をする3つの関数は、別ファイルに切り出して、
from hogehoge import set_logging_arguments, init_logging, log_environment_info
set_logging_arguments(parser)
args = parser.parse_args()
init_logging(args)
log_environment_info(args, logger=logger)
のように読み込むようにしてやれば、目障りではなくなるし使いまわしも簡単になる。。