概要
Pythonのclickでgroupを使うと1つのスクリプトに複数のサブコマンドを実装できる。
バージョン情報
- Python 3.7.4
- Click==7.0
最小限のサンプルコード
引数に応じて2つのコマンドを出し分けるシンプルなコード。
import click @click.group() def cli(): pass @cli.command() def create(): print('create command') @cli.command() def delete(): print('delete command') if __name__ == '__main__': cli()
上記をexample.pyという名前で保存。
手始めにサブコマンドを付けずに実行してみる。
$ python example.py Usage: example.py [OPTIONS] COMMAND [ARGS]... Options: --help Show this message and exit. Commands: create delete
ヘルプが表示された。
createとdeleteという2つのメソッドを用意したので、それぞれメソッドと同じ名前を引数に指定すれば当該処理が呼び出される。
$ python example.py create create command $ python example.py delete delete command
引数の指定
@click.optionで各コマンドが取る引数を指定する。
コマンドごとにそれぞれ違う引数のパターンを指定できる。
import click @click.group() def cli(): pass # createはnameを引数に取る @cli.command() @click.option('-n', '--name') def create(name): print('create %s' % name) # deleteは引数を取らない @cli.command() def delete(): print('delete command') if __name__ == '__main__': cli()
helpの参照。
$ python example.py create --help Usage: example.py create [OPTIONS] Options: -n, --name TEXT --help Show this message and exit.
コードで@click.option('-n', '--name')と指定しているので、-nもしくは--nameで値を指定できる。
$ python example.py create --name foo create foo
pass_contextの利用
@click.pass_contextを指定するとclick.core.Contextが引数で渡される。
Contextのobjに引数を登録することで、pass_contextを指定した各コマンドに対して、共通の値を送ることができる。
import click @click.group() @click.option('--debug/--no-debug', default=False) @click.pass_context def cli(ctx, debug): ctx.obj = {'debug': debug} @cli.command() @click.option('-n', '--name') @click.pass_obj def create(obj, name): print('debug -> %b, name -> %s', (obj['debug'], name)) @cli.command() @click.pass_obj def delete(obj): print('debug -> %r' % obj['debug']) if __name__ == '__main__': cli()
呼び出し方は、cliの引数、コマンド名、指定コマンドの引数の順。
$ python example.py --debug create --name foo debug -> True, name -> foo
invoke_without_commandの指定
invoke_without_command=Trueを指定すると、サブコマンドを指定しない場合でも処理が呼び出される。
例えば下記のコード。
invoke_without_commandの指定がない場合はヘルプが表示されたが、指定するとcli()が呼び出されて「cliが呼ばれました」と標準出力に表示される。
import click @click.group() def cli(): print('cliが呼ばれました') @cli.command() def create(): print('create command') @cli.command() def delete(): print('delete command') if __name__ == '__main__': cli()
サブコマンドの記述を複数のファイルに分ける
サブコマンドが増えていって記述を分けたい気分になってきた場合の対処方法。
commands.py(仮名)というファイル名で、コマンドのところだけ書いたPythonファイルを用意する。
import click @click.command() @click.option('--name', required=True) def create(name): print('create command : name=%s' % name) @click.command() def delete(): print('delete command')
mainを記述している example.py の方で、command.pyにimportして記述したコマンドをadd_commandする。
import click from commands import create, delete @click.group() def cli(): pass cli.add_command(create) cli.add_command(delete) if __name__ == '__main__': cli()
実行してみる。
$ python example.py create --name foo create command : name=foo
改定履歴
Author: Masato Watanabe, Date: 2019-11-16, 記事投稿