はじめに
Qiitaのコメントで、紹介してもらったclickを調べてみたら、簡単にサブコマンドを実装できることが分かったので、そのやり方をまとめておく。サブコマンドとは、スクリプトの第一引数が、コマンドになっているような形態のコマンドで、git, svnなどのバージョン管理コマンドや、djangoのプロジェクト管理スクリプトmanage.pyなどにみられる形式だ。
環境構築
clickは、pythonの標準パッケージではないので、pipでインストールする。
$ pip install click
基本
基本的なコードは以下のようになる。
import click
@click.group(invoke_without_command=True)
@click.pass_context
def cli(ctx):
if ctx.invoked_subcommand is None:
print ctx.get_help()
else:
print('gonna invoke %s' % ctx.invoked_subcommand)
@cli.command(help='description 1')
@click.argument('target', required=False)
def subcommand1(target):
print "sub command 1"
@cli.command(help='description 2')
@click.argument('target', required=False)
def subcommand2(target):
print "sub command 2"
if __name__ == '__main__': cli()
cliがすべての起点になる関数となり、subcommand1とsubcommand2がそれぞれサブコマンドの実装になる。それぞれの説明はhelp変数として、@cli.commandに入力する。以下、コマンドのhelpを表示した内容を示す。
Usage: sample.py [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
subcommand1 description 1
subcommand2 description 2
Commandsにsubcommand1,2が登録されているのがわかる。
Tips
ショートカットの作成
(サブ)コマンド名が長すぎて、ショートカットコマンドを作りたい場合がある。その場合は、Groupクラスを拡張して実装する。
...
class AliasedGroup(click.Group):
def get_command(self, ctx, cmd_name):
rv = click.Group.get_command(self, ctx, cmd_name)
if rv is not None:
return rv
if cmd_name == 'shortcut':
return click.Group.get_command(self, ctx, 'subcommand1')
return None
@click.group(cls=AliasedGroup, invoke_without_command=True)
@click.pass_context
def cli(ctx):
...
上記のように、@click.groupのcls引数として実装したAliasedGroupを指定する。すると、
$ python ./sample.py shortcut
gonna invoke shortcut
sub command 1
上記のようにsabcommand1の実装が動く。
通常のcommands実装をサブコマンドにする
複数のファイルに分割して、サブコマンドを実装したい場合は、コマンド実装をして、それをgroupにaddする方法があります。
@click.group(invoke_without_command=True)
@click.pass_context
def handle(ctx):
if ctx.invoked_subcommand is None:
print ctx.get_help()
else:
print('gonna invoke %s' % ctx.invoked_subcommand)
@click.command()
def hoge():
pass
handle.add_command(hoge)
今後
試し次第、連結コマンドの実装なども紹介していきたい。