Works by

Ren's blog

アプリケーションバックエンド中心に書いていきます

【python】コマンドラインパーサclick

clickとは

Welcome to the Click Documentation — Click Documentation (5.0)

clickpythonコマンドライン解析用モジュールです。
pythonスクリプトCLI上で実行したときに、コマンドライン引数のラベルを定義したり、ヘルプを表示するなどの機能を提供します。

rennnosukesann.hatenablog.com

前回の記事ではpython標準のコマンドラインパーサargparserを紹介しました。
今回はサードパーティ製のコマンドラインパーサclickの使用法を軽く紹介したいと思います。

Usage

pipclickをインストールします。

$ pip install click

これだけでOKです!

Source

基本形

clickでは、基本的に関数やメソッドにアノテーションを付加していきます。
ここがargparserとの大きな違いですね。

最初に、clickモジュールをインポートし、呼び出すトップレベルの関数に@click.command()アノテーションをつけてみましょう。

import click

@click.command()
def main():
    print()

if __name__ == '__main__':
    main()
$ python main.py --help
Usage: main.py [OPTIONS]

Options:
  --help  Show this message and exit.

これだけで、コマンドライン上でのヘルプメッセージがサポートされていることがわかります。

必須引数の設定

指定が必須な引数の設定は、@click.argument()アノテーションで行います。

import click

@click.command()
@click.argument("arg1") # 必須パラメータ定義
def main(arg1):
    print(arg1)

if __name__ == '__main__':
    main()

@click.argument()で指定した引数と関数の仮引数名(ここではarg1)は一致している必要があります。渡された引数はこの仮引数arg1に格納され、関数やメソッド内で利用することができます。

# ヘルプメッセージに引数情報が追加される
$ python main.py --help
Usage: main.py [OPTIONS] ARG1

Options:
  --help  Show this message and exit.

# NG(必須引数を指定していない)
$ python main.py       
Usage: main.py [OPTIONS] ARG1

Error: Missing argument "arg1".

# OK
$ python main.py test
test

引数を設定すると、ヘルプメッセージに引数の情報が追加されます。
必須引数はその名の通り必ず設定されている必要があります。
設定されていない場合、clickがエラーを送出します。

また指定した引数は指定順にコマンドライン引数値と対応付けされます。
例えば、上記の例ではarg1というコマンドライン引数がtestという値と対応付けされています。

オプション引数の指定

@click.option()で任意引数も定義することが可能です。

@click.command()
@click.option("--opt")
def main(option):
    print(option)

オプションの場合、オプション引数名が関数の引数名とハイフンを除いて一致している必要があります。

またオプション引数を指定した場合、実行時に引数の頭に明示的に名前を指定する必要があります。

# NG : 値だけ渡すのはだめ
$ python main.py option
Usage: main.py [OPTIONS]

Error: Got unexpected extra argument (option)

# OK
$ python main.py --opt option
option

# 指定しなくてもOK(指定しない場合、変数の値はNoneになる)
$ python main.py             
None

またオプション引数名は短縮形を登録することができます。

# OK
$ python main.py 
None

# OK
$ python main.py -o test
test

#OK
$ python main.py --opt test 
test

型指定

引数の型指定がtypeオプションで可能です。
引数が指定型で解釈できない文字列の場合、エラーとなります。

import click

@click.command()
@click.argument("arg1", type=float) # 型指定
def main(arg1):
    print(arg1)

if __name__ == '__main__':
    main()
# 引数がfloatで解釈できないので、エラー
$ python main.py test
Usage: main.py [OPTIONS] ARG1

Error: Invalid value for "arg1": test is not a valid floating point value

# OK
$ python main.py 3.14
3.14

複数値指定

一つの引数に複数の値をnargsオプションで設定できます。
nargsで設定した場合、引数はタプル値になります。

import click

@click.command()
@click.argument("arg1", type=float, nargs=3)
def main(arg1):
    print(arg1)

if __name__ == '__main__':
    main()
# NG 3つ引数が必要
$ python main.py 3.14
Error: argument arg1 takes 3 values

# OK
$ python main.py 3.14 1.23 4.44
(3.14, 1.23, 4.44)

またnargs=-1を指定すると、任意の数の引数をとることができるようになります。

@click.argument("arg1", type=float, nargs=-1)
$ python main.py 3.14 1.23 4.44 9.81 111. 
(3.14, 1.23, 4.44, 9.81, 111.0)

ただし、別の引数が後ろに追加された場合、末尾の引数が他の引数に割り当てられます。

@click.command()
@click.argument("arg1", type=float, nargs=-1)
@click.argument("arg2", type=float)
@click.argument("arg3", type=float)
def main(arg1, arg2, arg3):
    print(arg1)
    print(arg2)
    print(arg3)
# 9.81は`arg2`に、111.0は`arg3`に割り当てられる
$ python main.py 3.14 1.23 4.44 9.81 111.
(3.14, 1.23, 4.44)
9.81
111.0

フラグ指定

@click.optionに限り、true/falseを表すフラグを定義することができます。

import click

@click.command()
@click.option("--is_read/--is_unread", default=False)
def main(is_read):
    print(is_read)

if __name__ == '__main__':
    main()
$ python main.py           
False

$ python main.py --is_read  
True

$ python main.py --is_unread
False

まとめ

感想としては、コマンドライン引数の定義アノテーションで指定することで、

  • どこでコマンドライン引数が定義されているのか
  • どの関数が起点なのか(初期段階で呼ばれるのか)
  • どのような設定なのか

がわかりやすく、また設定自体もシンプルで使いやすい印象でした。

参考

Welcome to the Click Documentation — Click Documentation (5.0)