Pythonでコマンドラインツール(CUIとかCLI)を作るときのTips

PythonCUIとかCLIを作る際のTips です.

下記の内容を順に書いていきます

  • エラー表示を見やすくする
    • 使い方の説明
    • 実際のコード例
  • コマンドライン引数の処理
    • 使い方の説明
    • 実際のコード例

Tips は今後も追記していく予定です(最終更新: 2020-06-13)

エラー表示を見やすくする(使い方の説明)

coloredlogs モジュールを使うと、エラーメッセージをカラフルに見やすく表示できます

import coloredlogs, logging
coloredlogs.install(fmt="%(message)s", level=logging.DEBUG)

logging.error("Error")
logging.warning("No such file")
logging.debug("parameter is %d" % (123))

メッセージにはレベルが定義されています

レベル メソッド レベルの数値
logging.CRITICAL logging.critical() 50
logging.ERROR logging.error() 40
logging.WARNING logging.warning() 30
logging.INFO logging.info() 20
logging.DEBUG loggin.debug() 10

そして setLevel() でレベルを指定すると,その値より小さなレベルのメッセージは画面には表示されなくなります.

たとえば

logging.getLogger().setLevel(logging.WARNING)

logging.error("Error")
logging.warning("No such file")
logging.debug("parameter is %d" % (123))

を実行すると logging.debug()の部分は画面には表示されません

このようにデバッグ情報の表示のOn/Offなどを柔軟に切り替えることができます

エラー表示を見やすくする(実際のコード例)

coloredlogs は標準ではインストールされません.coloredlogsがインストールされてない場合はインストール方法を画面に表示するようにしておくと便利です

#!/usr/bin/env python3

import sys
try:
    import coloredlogs, logging
except ImportError as err:
    print("\nPlease install %s. You may install it by using:" % err.name)
    print(" pip3 install %s\n" % err.name)
    sys.exit("Abort.")

coloredlogs.install(fmt="%(message)s", level=logging.DEBUG)

モジュールがインストールされてない場合,ImportErrorの例外が発生します. そこで try: except で例外処理を実装します

ImportError例外は,例外を引数errで受けとると, err.name の値で例外を起こしたモジュール名が取得できます.


コマンドライン引数の処理(使い方の説明)

python標準モジュール argparse をつかいます

import argparse
parser = argparse.ArgumentParser()

# コマンドラインオプションを追加
parser.add_argument('filename', type=str, nargs='?')

# コマンドライン引数を処理
args = parser.parse_args()

# コマンドライン引数は args のメンバ変数になります
print(args.filename)

parse_add_argument の使い方

add_argumentの使い方:コマンドライン引数の追加
parser.add_argument('filename', type=str, nargs='?')

args = parser.parse_args()

print(args.filename)
add_argumentの使い方:引数不要のオプションの追加

action='store_true' を指定します

parser.add_argument('--list', action='store_true', help='show a list of dataset')
args = parser.parse_args()

print(args.list)
add_argumentの使い方:引数必須のオプションの追加
parser.add_argument('--value')
args = parser.parse_args()

print(args.value)
add_argumentの使い方:複数回指定できる引数なしオプション
parser.add_argument('-v', '--verbose', action='count', help='Increase verbosity level.')
args = parser.parse_args()

print(args.verbose)

動作は

  • コマンドラインで -v がN回指定されていれば args.verboseの値は N
  • "-v" が一回も指定されていなければ args.verbose の値は None

になります


コマンドライン引数の処理(実際のコード例)

コマンドラインオプション "-v" で,デバッグメッセージの表示をOn/Offするサンプルです

コマンドライン引数で,以下の動作をします

$ ./sample.py   --help    # ヘルプメッセージを表示
$ ./sample.py         #  warning のメッセージまで表示
$ ./sample.py -v     #  info のメッセージまで表示
$ ./sample.py -vv   #  debug のメッセージまで表示

sample.pyの中身

#!/usr/bin/env python3

import sys
import argparse

try:
    import coloredlogs, logging
except ImportError as err:
    print("\nPlease install %s. You may install it by using:\n" % (err.name))
    print(" pip3 install %s\n" % (err.name))
    sys.exit("Abort.")
else:
    coloredlogs.install(fmt="%(message)s", level=logging.DEBUG)


parser = argparse.ArgumentParser()
parser.add_argument('-v', '--verbose', action='count', help='Increase verbosity level.')

args = parser.parse_args()

if args.verbose is None:
    logging.getLogger().setLevel(logging.WARNING)
else:
    table = [logging.WARNING, logging.INFO, logging.DEBUG]
    level = min(len(table)-1, args.verbose)
    logging.getLogger().setLevel(table[level])

logging.critical("critical message")
logging.error("error message")
logging.warning("warning message")
logging.info("info message")
logging.debug("debug message")