-vvvや-qで作ったコマンドのloggingレベルを変更する斬新なコード
はじめに
argparse にcountというactionがあり、これを使うと渡した同一オプションの数をカウントすることができます。
これを使って、例えば、curlやsshなどで見られる -v
や -vv
の記述に似せたものをやろうという話です。
基本的な考え方は以下です。
- defaultは
logging.WARN
-v
オプションは loggingレベルを下げる-q
オプションは loggingレベルを上げる
logging
また、logging はNOTSET,DEBUG,INFO,WARNING,ERROR,CRITICALという順にdefaultのloggingレベルが設定されています。が、これらは単なる数値です。
import logging print(logging.NOTSET) # => 0 print(logging.DEBUG) # => 10 print(logging.INFO) # => 20 print(logging.WARNING) # => 30 print(logging.ERROR) # => 40 print(logging.CRITICAL) # => 50
argparse
argparseのcountを使って引数に渡されたvの数を数える事ができます。(http://docs.python.jp/3/library/argparse.html#action から引用)
'count' - このアクションはキーワード引数の数を数えます。例えば、verboseレベルを上げるのに役立ちます:
>>> parser = argparse.ArgumentParser() >>> parser.add_argument('--verbose', '-v', action='count') >>> parser.parse_args('-vvv'.split()) Namespace(verbose=3)
そんなわけで、以下のようなコードを書くと、オプションによって手軽にloggingレベルを調節できるようになります。
# -*- coding:utf-8 -*- # program.py import argparse import logging import sys logger = logging.getLogger(__name__) parser = argparse.ArgumentParser() parser.add_argument('-v', '--verbose', action='count', default=0) parser.add_argument('-q', '--quiet', action='count', default=0) args = parser.parse_args(sys.argv[1:]) logging_level = logging.WARN + 10*args.quiet - 10*args.verbose logging.basicConfig(level=logging_level) logger.debug("debug") logger.info("info") logger.warning("warning") logger.error("error") logger.critical("critical")
以下の様に使えます。 -v
も -q
も多すぎてもエラーにはなりません。
# defaultはwarning $ python program.py WARNING:__main__:warning ERROR:__main__:error CRITICAL:__main__:critical # -vでlogging levelを下げられる $ python program.py -vv DEBUG:__main__:debug INFO:__main__:info WARNING:__main__:warning ERROR:__main__:error CRITICAL:__main__:critical # -qでlogging levelを上げられる $ python program.py -q ERROR:__main__:error CRITICAL:__main__:critical # やりたければ2つを混ぜあわせても $ python program.py -vv -q INFO:__main__:info WARNING:__main__:warning ERROR:__main__:error CRITICAL:__main__:critical # hmm $ python program.py -vvvvvvv DEBUG:__main__:debug INFO:__main__:info WARNING:__main__:warning ERROR:__main__:error CRITICAL:__main__:critical
便利ですね。これは元々redditのコメントにあった内容です(https://www.reddit.com/r/Python/comments/3nctlm/what_python_tools_should_i_be_using_on_every/cvn0ybf)。