エンジニア

PythonCLIフレームワークcliffを触ってみる

投稿日:2015年3月27日 更新日:

今回のエンジニアブログを担当する藤岡です。
よろしくお願いします。

今回は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

実行結果はこちら。
スクリーンショット 2015-03-26 12.41.05
アプリケーション内のhelloコマンドが実行され、Helloクラスのtake_action関数が呼ばれていることが確認出来ました。

また、cliffではデフォルトで様々なオプションが追加されており、ヘルプ等のオプションをサポートしてくれます。
スクリーンショット 2015-03-26 11.48.28

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関数によりコマンドライン引数を追加しています。


実行結果はこちら。
スクリーンショット 2015-03-26 12.01.09
コマンドライン引数の受け取りが出来ています。

また、add_argument関数内のmetavar, helpを指定することで、コマンドの説明を明示する事ができます。
スクリーンショット 2015-03-26 12.01.32

3, インタラクティブシェル

引数なしでアプリケーションを実行するとインタラクティブシェルが動き出します。
インタラクティブモードでは、各コマンドを打ち込むだけで実行結果を出力することが出来ます。

スクリーンショット 2015-03-26 12.56.05

以上になります。
CLIアプリケーションを簡潔に作ることが出来るので、是非お試し下さい。

採用情報

ワンダープラネットでは、一緒に働く仲間を幅広い職種で募集しております。

-エンジニア
-

© WonderPlanet Inc.