業務中に繰り返し行う作業を社内コマンドとしてまとめています。
その中で共有できそうな知見がいくつか出てきたのでSENSY Advent Calendar 2018で数回に分けて紹介していきます。
今回は、サブコマンドの作り方を紹介します。
サブコマンド
この記事でサブコマンドとは、git clone
やgit checkout
のようなあるコマンド(git
)の配下にさらに別のコマンド(clone
やchekcout
)を用意すること言います。clickのドキュメントでは、Nesting Commandsという名前がついているようです。
サブコマンドをclickで実現するためには、Group
という複数のコマンドをひとまとめにできる機能を使います。
Groupを使ってコマンドをまとめる
次の内容でservice.py
を用意してください。
import click
@click.group()
def service():
pass
@service.command()
@click.option('--name', '-n', required=True)
def create(name):
click.echo(f'create {name}')
@service.command()
def list():
click.echo('show list!!')
if __name__ == '__main__':
service()
ここで軽くコードの説明をします。
まず、3行目の@click.group()
でサブコマンドを集約するためのグループとして関数service()を登録しています。
つづいて、7,11,15行目の@service.command()
でserviceコマンドのサブコマンドになる処理を登録しています。
サブコマンドの動作を確認
ここまで書けたら、前回と同じようにsetup.pyを用意してください。
from setuptools import setup
setup(
name='service',
version='0.1',
py_modules=['service'],
install_requires=[
'Click',
],
entry_points='''
[console_scripts]
service=service:service # serviceコマンドにservice.pyの関数service()を紐づける
''',
)
インストールしてコマンドを実行すると、サブコマンドが作成されていることがわかります。
サブコマンドによって実行内容が切り替わっていますね。
(venv) $ pip install -e .
(venv) $ service create --name newservice
create newservice
(venv) $ service list
show list!!
サブサブコマンド
Gitのような単一のサービスのコマンドだけであればサブコマンドを利用できれば十分かもしれません。
しかし、社内向けのコマンドツールとしては、社内で利用されている様々なコマンドを体系的にまとめあげたいところです。そこで、aws s3 ls
やgcloud app deploy
を参考に<コマンド> <サービス> <操作>
というコマンド体系にしていきます。
これはを実現するには下記の2パターンが考えられます。
- サブコマンドの最初のオプションで処理を切り替える
- サブコマンドをネストする
今回は後者の「サブコマンドをネストする」パターンを紹介します。
サブコマンドをネストする
同じディレクトリに次の内容でcompany.py
を用意してください。
import click
from service import service
@click.group()
def company():
pass
# グループのサブコマンドにグループを登録
company.add_command(service)
if __name__ == '__main__':
company()
先程と同様にcompanyというグループを作成しました。
そして、そこにcompany.add_command(service)
で先程作ったグループのserviceを登録しています。
サブコマンドのネストはこれで完成です。
サブサブコマンドの動作を確認
それでは動作を確認してみましょう。
setup.pyを変更し、エントリポイントがcompany.pyから始まるようにします。
from setuptools import setup
setup(
-- name='service',
++ name='company',
version='0.1',
-- py_modules=[, 'service'],
++ py_modules=['company', 'service'],
install_requires=[
'Click',
],
entry_points='''
[console_scripts]
-- service=service:service
++ company=company:company
''',
)
先ほどインストールしていたserviceコマンドはもう不要なので先にアンインストールしてます。
その後、companyコマンドをインストールし動作を確認してみましょう。
# 不要になったserviceコマンドをアンインストール
(venv) $ pip uninstall service
(venv) $ pip install -e .
# 引数なしだとデフォルトでヘルプが表示される。Commandsにサブコマンドserviceが登録されている
(venv) $ company
Usage: company [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
service
# サブサブコマンドの実行
(venv) $ company service create --name newservice
create newservice
(venv) $ company service list
show list!!
意図した通りに動きました!!
まとめ
今回はclickでサブコマンドを登録方法を紹介しました。また、それをネストさせてみました。
これだけのコードでaws s3 ls
のような階層構造のコマンド体系を簡単に用意できます。
サブコマンドは、複数のコマンドをまとめ上げたいときは非常に便利なのでぜひ使ってみてください。