こないだ、clizeというpythonライブラリを見つけました。
なかなかいいライブラリだったので、紹介します。
このclizeですが、何をしてくれるのかというと、CLIの簡単作成です。
「いやいや、fireで間に合ってますけど。」って思った方もいると思います。
今回は、pythonでCLIを作る際によく使うライブラリを比較しつつ、clizeについて紹介できればと思います。
python CLIライブラリ比較
python CLIライブラリは、clizeを含めて下の3つを押さえておけばいいのかなと勝手に思っています。
この3つを、簡単な算数のスクリプトを作成するサンプルで比較していきます。
1. argparse
argparseは、pythonの標準ライブラリです。
標準ライブラリと考えるとよくできていますが、コード量が多く、「ん?これなんだっけ?」となりがちです。
コードはこんな感じになります。
def main(a: int, b: int, c: float=0.5):
"""
a × b × c を実行し、結果を返す。
:param a: 整数を入力してください。
:param b: 整数を入力してください。
:param c: 浮動小数点数を入力してください。何も入力しなければ、自動的に0.5が選択されます。
:return: a × b × c
"""
return a * b * c
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("a", type=int,
help="整数aを入力してください。")
parser.add_argument("b", type=int,
help="整数bを入力してください。")
parser.add_argument("c", type=int, default=0.5,
help="浮動小数点数を入力してください。何も入力しなければ、自動的に0.5が選択されます。")
args = parser.parse_args()
main(args.a, args.b, args.c)
定義も面倒ですし、値を取得する際にargs.a
などと書く必要があり、さらに面倒です。
main(a, b, c)
の引数が仕様変更された場合などに、「えーっと、なんだっけ?」となりがちです。
helpはこんな感じ。
$ python argparse-sample.py --help
usage: sample.py [-h] a b c
positional arguments:
a 整数aを入力してください。
b 整数bを入力してください。
c 浮動小数点数を入力してください。何も入力しなければ、自動的に0.5が選択されます。
optional arguments:
-h, --help show this help message and exit
2. fire
続いてのfireは、Google製のライブラリです。
これが一番使われているのかなと勝手に思っています。
argparseに比べて、「CLI生成を自動化しているぞ!」という気持ちになりやすいです。
def main(a: int, b: int, c: float=0.5):
"""
a × b × c を実行し、結果を返す。
:param a: 整数を入力してください。
:param b: 整数を入力してください。
:param c: 浮動小数点数を入力してください。何も入力しなければ、自動的に0.5が選択されます。
:return: a × b × c
"""
return a * b * c
if __name__ == '__main__':
import fire
fire.Fire(main)
fire.Fire(main)
だけで、関数を丸ごとCLI化することができます。
また、クラスについても、class MyClass(fire.Fire)
とするだけで、全メソッドをCLI化することができます。
ただ、不便な点もあります。
-
-- --help
という変なヘルプの出力方法。 - 変数の説明を表示できない。多分。(知ってたら教えてください。。。)
- 変数の型を勝手に変えてきて、時々うざい。
ヘルプはこんな感じ。
$ python fire-sample.py -- --help
Type: function
String form: <function main at 0x108d67e18>
File: ~/Repos/projects/kito-xgx-autotuning/bin/sample.py
Line: 38
Docstring: a × b × c を実行し、結果を返す。
:param a: 整数を入力してください。
:param b: 整数を入力してください。
:param c: 浮動小数点数を入力してください。何も入力しなければ、自動的に0.5が選択されます。
:return: a × b × c
Usage: sample.py A B [C]
sample.py --a A --b B [--c C]
docstringが表示されるので、申し訳程度に説明を書くことはできますが。。。
また、型の自動変換についても、クセが強いです。
公式からのコピペですが、例えばこんな動き。
import fire
fire.Fire(lambda obj: type(obj).__name__)
$ python example.py 10
int
$ python example.py 10.0
float
$ python example.py hello
str
$ python example.py '(1,2)'
tuple
$ python example.py [1,2]
list
$ python example.py True
bool
$ python example.py {name: David}
dict
$ python example.py 10
int
$ python example.py "10"
int
$ python example.py '"10"'
str
$ python example.py "'10'"
str
$ python example.py \"10\"
str
役立つこともあるんですが、たまにうざい。
古いバージョンでは四則演算機能までついていたので、日付を2019-10-25
のように書くと、引き算されて1984
になってしまったこともありました。
3. clize
そして、本題のclize。clizeのいいところは、下の通り。
- fireとほぼ同じ感覚でCLI自動作成をできる。
-
--help
や-h
でヘルプが出る。 - docstringをパースし、ヘルプに表示してくれる。
- type annotationを見て、型を変換してくれる。
もちろん、ダメなところもあります。
-
--a 10
や-a 10
のような書き方ができず、常に10 20 abc
のような書き方しかできない。
結構致命的ですね。--a 10
や-a 10
のフォーマットに対応してくれたら最高なのに。追加してPR出そうかな。。。
コードはこんな感じ。
def main(a: int, b: int, c: float=0.5):
"""
a × b × c を実行し、結果を返す。
:param a: 整数を入力してください。
:param b: 整数を入力してください。
:param c: 浮動小数点数を入力してください。何も入力しなければ、自動的に0.5が選択されます。
:param d: 文字列を入力してください。何も入力しなければ、自動的にabcが選択されます。
:return: a × b × c
"""
return a * b * c
if __name__ == '__main__':
from clize import run
run(main)
ヘルプはというと、
$ python clize-sample.py --help
Usage: bin/sample.py a b [c]
a × b × c を実行し、結果を返す。
Arguments:
a 整数を入力してください。 (type: INT)
b 整数を入力してください。 (type: INT)
c 浮動小数点数を入力してください。何も入力しなければ、自動的に0.5が選択されます。 (type: FLOAT, default: 0.5)
Other actions:
-h, --help Show the help
docstringをパースし、typeや説明を表示してくれています。
このhelp画面が最高です。
まとめ
最後に3ライブラリの特徴をまとめると、
- argparse: 公式ライブラリ。コード量が多い。
- fire: 簡単。ただし、ヘルプや型などクセが強い。
- clize: 簡単。docstringやtype annotationを使ってくれる。ただし、
--a
のような書き方ができない。
いかがでしたか?あれ、「案外clizeいいやつじゃん」と思っていただけた方がいれば幸いです。
「clizeに-a
つけるぞ!」って方がいれば、ぜひ頑張って欲しいです。
以上、clizeの紹介でした。これ誰が読むんやろ。