今回のエンジニアブログを担当する藤岡です。
よろしくお願いします。
今回はcliffというライブラリを使用して、簡単なCLIツールを作ってみたいと思います。
CLIツールはバッチ処理、簡単な自作ツールを作成する際に役に立つかと思います。
cliffは3rd party製のPythonCLIアプリケーションフレームワークです。
複数のコマンドの追加、コマンドライン引数の解析、ログの出力等の機能を補ってくれます。
こちらにパッケージの情報が記述してあります。
pipを使用することで簡単にインストールすることが出来ます。
pip install cliff
今回は簡単な出力を出しながら、cliffの機能について触れていきたいと思います。
今回作成するツールのディレクトリ構成は以下のようになっております。
sample_app | |-- sample_app | |-- __init__.py | |-- hello.py | |-- main.py |-- setup.py
1, 必須となる機能の実装
■ 大本となるアプリケーションの実装
cliffでは、アプリケーションクラスを軸として様々なコマンドを実行していきます。
main.py
# -*- coding: utf-8 -*- from cliff.app import App from cliff.commandmanager import CommandManager import sys import logging class SampleApp(App): def __init__(self): super(SampleApp, self).__init__( description=u'sample application', version=u'0.1', command_manager=CommandManager(u'sample_app.command'), ) def main(argv=sys.argv[1:]): sample_app = SampleApp() return sample_app.run(argv)
cliff.app.Appを継承したクラスはツールの軸となる、アプリケーションに紐付けられます。
このAppクラスに様々なコマンドを登録し、呼び出すことが可能になります。
cliff.app.Appを継承したクラスは、run関数を呼ぶことで実行されます。
上記のコードだと、main関数が呼び出されることで、アプリケーションが動き出します。
CommandManagerのコンストラクタ引数では、setup.pyに記述されているentry_pointグループ名を渡します。
そうすることで、entry_point内のコマンド達を取得することが出来ます。
■ コマンドの実装
それでは、上記で作成したSampleAppに簡単な出力を行うhelloコマンドを登録してみます。
hello.py
# -*- coding: utf-8 -*- from cliff.command import Command class Hello(Command): "A Hello command that prints a message." def take_action(self, parsed_args): print u'Hello!! sample application!!'
cliff.command.Commandを継承したクラスはアプリケーションのコマンドとして実装可能になります。
コマンドクラスは、コマンド実行時にtake_action関数が呼び出されます。
上記のコードだと、"Hello!! sample application!!"と出力されるはずです。
■ setup.pyの実装
cliffのコマンドの実装はsetup.pyのentry_pointに記述をすることで実装することが可能です。
setup.pyの詳細は割愛させていただきます。
詳細はこちら。
・cliffパッケージが必須となるのでinstall_requires要素内にcliffの記述を忘れない
・エントリーポイント要素内に登録したいコマンドのエントリーポイントグループを記述する(下記の例ですとsample_app.commandの部分です)
cliffアプリケーションのsetup.pyでは、この2つの実装が大切になってきます。
setup.py(一部分)
install_requires=[ u'cliff', ], entry_points={ u'console_scripts' : [ u'sampleapp = sample_app.main:main', ], u'sample_app.command' : [ u'hello=sample_app.hello:Hello', ], },
各コマンドの登録フォーマットですが、
{アプリケーション名}={モジュール名}:{関数}
{コマンド名}={モジュール名}:{クラス名}
てな感じになってます。
上記の例ですと、sampleappコマンドはsample_appモジュール内のmainモジュールのmain関数を呼びだし、helloコマンドはsample_appモジュール内のhelloモジュールのHelloクラスを呼び出しています。
必要な実装が終わったら、アプリケーションをインストールします。
下記のコマンドで、作成したCLIアプリケーションをインストール出来ます。
python setup.py install
実行結果はこちら。
アプリケーション内のhelloコマンドが実行され、Helloクラスのtake_action関数が呼ばれていることが確認出来ました。
また、cliffではデフォルトで様々なオプションが追加されており、ヘルプ等のオプションをサポートしてくれます。
2, コマンドライン引数の実装
cliffでは、コマンド毎にコマンドライン引数を設定することが可能です。
引数を受け取って、argument valueを出力してみます。
hello.py
# -*- coding: utf-8 -*- from cliff.command import Command class Hello(Command): "A Hello command that prints a message." def get_parser(self, prog_name): parser = super(Hello, self).get_parser(prog_name) parser.add_argument(u'--arg1', default=None, metavar=u'<引数1>', help=u'引数1') parser.add_argument(u'--arg2', default=None, metavar=u'<引数2>', help=u'引数2') parser.add_argument(u'--arg3', default=None, metavar=u'<引数3>', help=u'引数3') return parser def take_action(self, parsed_args): print parsed_args.arg1 print parsed_args.arg2 print parsed_args.arg3 print u'Hello!! sample application!!'
cliffのCommandクラスを継承したクラスでget_parser関数をオーバーライドし、その中でadd_argument関数によりコマンドライン引数を追加しています。
実行結果はこちら。
コマンドライン引数の受け取りが出来ています。
また、add_argument関数内のmetavar, helpを指定することで、コマンドの説明を明示する事ができます。
3, インタラクティブシェル
引数なしでアプリケーションを実行するとインタラクティブシェルが動き出します。
インタラクティブモードでは、各コマンドを打ち込むだけで実行結果を出力することが出来ます。
以上になります。
CLIアプリケーションを簡潔に作ることが出来るので、是非お試し下さい。