PythonのコマンドラインパーサーであるClickを使ってみた

Pythonコマンドラインインターフェースを作ろうとした時、わりと最近はコマンドラインパーサーにclickが使われていることが少しだけ多い印象?だったので、個人的に少し触ってみた。

コマンドラインパーサーとしては他にも標準ライブラリに組み込まれているargparseなどがある。

Clickとは

Clickは必要なコードを最小限に抑えて、コマンドラインインターフェースを作成するためのパッケージ。

デコレータをちょちょっとつけるだけでいい感じにコマンドラインインターフェースが作れて便利な印象。

click.palletsprojects.com

基本的な使い方

PyPI経由でインストール

$ pip install click

@click.command()デコレータを使って関数を修飾し、コマンドを登録する

import click


@click.command()
def hello():
    click.echo('Hello, World!')


if __name__ == '__main__':
    hello()

実行してみると

$ python hello.py
Hello, World!

これだけだと普通のpythonスクリプトを実行しているのと同じだが、--helpオプションをつけて実行すると

$ python hello.py --help
Usage: hello.py [OPTIONS]

Options:
  --help  Show this message and exit.

CLIっぽくhelpが表示されているのがわかる。

オプションを追加する

@click.optionデコレータを使って関数を修飾することで簡単にオプションを追加することができる。

オプションで指定した値が関数の引数となり、関数内で使用できるようになる。

オプションが指定されなかった場合、変数の値はNoneとなる。

import click


@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', '-n', help='The person to greet.')
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo(f'Hello {name}')


if __name__ == '__main__':
    hello()

この例だとcountnameの二つのオプションを追加している。

nameオプションは--name-nの両方で指定できるように

@click.option('--name', '-n', help='The person to greet.')

のような感じでデコレータにパラメータを渡している。

また、helpパラメータでオプションの説明を追加、defaultパラメータでオプションが指定されてなかった時のデフォルト値を指定することができる。

実行してみるとこんな感じ

$ python option.py --count 3 -n Ryo
Hello Ryo
Hello Ryo
Hello Ryo

--helpオプションを渡して実行するとhelpパラメータで追加したオプションの説明がここで表示される。

$ python option.py --help
Usage: option.py [OPTIONS]

  Simple program that greets NAME for a total of COUNT times.

Options:
  --count INTEGER  Number of greetings.
  -n, --name TEXT  The person to greet.
  --help           Show this message and exit.

引数を追加する

こちらも@click.argumentデコレータを使って関数を修飾するこで簡単に追加できる。

オプションと同様、引数で指定した値が関数の引数となり、関数内で使用できるようになる。

import click


@click.command()
@click.argument('name')
def hello(name):
    click.echo(f'Hello, {name}')


if __name__ == '__main__':
    hello()

実行してみるとこんな感じ

$ python arguments.py Ryo
Hello, Ryo

ここでは、オプションと違って、引数の指定がなかった場合はエラーとなる。

$ python arguments.py
Usage: arguments.py [OPTIONS] NAME
Try 'arguments.py --help' for help.

Error: Missing argument 'NAME'.

サブコマンドの実装

clickではコマンドをグループ化することができ、これによってサブコマンドを作ることができる。

@click.groupデコレータを追加してエントリポイントとなる関数を修飾する。

import click


@click.group()
def cli():
    pass


@cli.command()
def command1():
    click.echo('execute command1')


@cli.command()
def command2():
    click.echo('execute command2')


if __name__ == '__main__':
    cli()

@<関数名>.commandとしてデコレータを追加してあげることで、それぞれのサブコマンドを登録することができる。

実行するとこんな感じ。

$ python subcommand.py command1
execute command1

$ python subcommand.py command2
execute command2

--hellpオプションを渡して実行してみると、サブコマンドの説明も表示されるようになる。

$ python subcommand.py
Usage: subcommand.py [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  command1
  command2

まとめ

argparseを使用したことがないので、単純に比較はできないが、デコレータを追加していくだけで、いろいろ出来るのでとても使いやすい。

次回はさらに細かくパラメータを指定したり、CLIのテストについてもまとめていきたいと思う。

サンプルコード

今回使ったサンプルコードはこちら。 github.com