Pythonパッケージ: 便利なコマンドラインパーサClickを使ってみる
概要
コマンドラインパーサとして、argparse
と呼ばれるPythonの標準パッケージが存在するが、使い勝手がいまいちだと感じています(あくまで個人的な感想ですが…)。
今回は、たまたま見つけたclick
と呼ばれるサードパーティ製のPythonパッケージを用いてコマンドラインの引数を解釈するコードを書いてみようと思います。
argparse
と比較してclick
の書き方だと、コードが書きやすく、あとから読み返しやすくなると感じます。
Clickのドキュメントはこちら。
http://click.pocoo.org/6/
内容
すでに、こちらのブログに詳しく解説されているのでここでは忘備録的な記載に留めようと思います。
インストール
AnacondaもしくはBiocondaがインストールされていることが前提。
conda install click
基本的な使い方
@click.command()
デコレータを用いて関数を修飾するだけでOK。
print
関数の代わりにclick.echo
を用いて文字列を標準出力することもできる。
@click.command() def cmd(): click.echo("Command was Done.")
続けて、@click.option()
デコレータに任意のオプションを追加していくことができる。argparseと同様に、-i
や--ifastq
などのような-
から始まるコマンドライン引数を指定することができる。
@click.command() @click.option('-i', '--ifastq') def cmd(): click.echo("Command was Done.")
また、作成したオプションに代入された値を取得するために、ifastq
のように-
を付けない形で文字列を指定することで、関数の中で値が代入された変数として扱えます。
以下のように、cmd
関数の引数にifastq
を指定しておく必要がある。
@click.command() @click.option('-i', '--ifastq', 'ifastq') def cmd(ifastq): click.echo(ifastq)
help
でHelpが呼び出されたときの説明文を指定できる。
@click.command() @click.option('-i', '--ifastq', 'ifastq', help='Input file in FASTQ file.') def cmd(ifastq): click.echo(ifastq)
実行例
#/usr/bin/env python import click @click.command() @click.option('-i', '--ifastq', 'ifastq', help='Input file in FASTQ file.') @click.option('-o', '--output-prefix', 'output', help='Prefix of output file.') def cmd(ifastq, output): click.echo(ifastq) def main(): cmd() if __name__ == '__main__': main()
実行すると、
$ python test.py -i test.fastq test.fastq $ python test.py --help Usage: test.py [OPTIONS] Options: -i, --ifastq TEXT Input file in FASTQ file. -o, --output-prefix TEXT Prefix of output file. --help Show this message and exit.
コマンドライン引数のタイプを指定したい
INT型やFLOAT型など、引数のタイプがあらかじめわかっている場合、引数のタイプを指定しておきたいケースが出てくる。
そういった場合、以下のようにargparseのときのように@click.option()
デコレータ内で指定することが可能。
type=<type>
で指定。
@click.option('-m', '--minimum-length', 'minimum_length', type=int, default=18, help='Discard trimmed reads that are shorter than LENGTH. Default: 18')
パラメータタイプは、int、float、bool、strが指定できるようです。
http://click.pocoo.org/6/parameters/
デフォルトの値を決めておきたい
特定のオプションでデフォルト値を指定しておきたいケースがある。 その場合、デフォルト値の設定は以下のように行う。
default='hogehoge'
で指定。
@click.option('-nl', '--nucleotide-trimming-list', 'nucleotide_trimming_list', default='A,N', help='Trimmed nucleotide list. Default: A,N')
指定する引数を限定したい
オプションの引数として、特定の文字列や数値しか受け付けたくない場合、以下のように指定できる引数を限定することができる。
type=click.Choice(['hoge', 'huga'])
で指定。
@click.option('-nd', '--nucleotide-trimming-direction', 'nucleotide_trimming_direction', type=click.Choice(['three', 'five']), help='Trimmed nucleotide direction. Default: three')
Helpパラメータをカスタマイズしたい
Clickのデフォルトでは、Help文は--help
を指定することで出力される。
一般的に、Help文は--help
だけでなく-h
でも出力されるケースが多い。そこで、-h
でもHelp文が出力されるように設定を変更する。
@click.command()
デコレータ内で指定。
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) @click.command(context_settings=CONTEXT_SETTINGS)
サブコマンド(後述)を利用している場合は、@click.group
デコレータ内で指定する。
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) @click.group(context_settings=CONTEXT_SETTINGS)
コールバック関数で値を検知・Helpを表示
オプションの引数を評価したい場合、コールバック関数を利用すると便利です。
@click.option()
デコレータ内でcallback=<function名>
を指定する。
また、コールバック関数内で、ctx.get_help()
でHelp文を表示させることができる。ctx.exit()
でPythonスクリプトの実行を止めることができる。
def validate_ifastq(ctx, param, value): if not value: click.echo('Error: Do not choose your FASTQ file.\n') print(ctx.get_help()) ctx.exit() return(value) @cmd.command() @click.option('-i', '--ifastq', 'ifastq', callback=validate_ifastq, help='Input file in FASTQ file. [required]')
サブコマンドを用意したい場合
@click.group()
デコレータを用いて、サブコマンドを利用することができます。
#/usr/bin/env python import click @click.group() def cmd(): pass @cmd.command() @click.option('-i', '--ifastq', 'ifastq', help='Input file in FASTQ file.') @click.option('-o', '--output-prefix', 'output', help='Prefix of output file.') def trim_polya(ifastq, output): click.echo('Start trimming polyA sequence from reads...') @cmd.command() @click.option('-i', '--ifastq', 'ifastq', help='Input file in FASTQ file.') @click.option('-o', '--output-prefix', 'output', help='Prefix of output file.') def get_pass_read(ifastq, output): click.echo('Start getting polyA site-supporting reads...') def main(): cmd() if __name__ == '__main__': main()
Help文は以下のとおり。
$ python test.py --help Usage: test.py [OPTIONS] COMMAND [ARGS]... Options: --help Show this message and exit. Commands: get_pass_read trim_polya
サブコマンドごとのオプションをHelp文で出力することもできる。
$ python test.py get_pass_read --help Usage: test.py get_pass_read [OPTIONS] Options: -i, --ifastq TEXT Input file in FASTQ file. -o, --output-prefix TEXT Prefix of output file. --help Show this message and exit.