docpotを使ってPythonで引数処理!

pythonで引数処理を行う方法を伝授しようと思います。

引数を処理する方法として、自分でゴリゴリ書くやら、他のツールを使うやらいくつか方法があると思いますが、
最近docoptという強力なツールを発見して、とても開発が捗っています。

今回はdocoptの使い方を見ていきましょう。

docoptのインストール

docoptはpipを用いてインストールすることができます。

$ pip install docopt

簡単ですね。

docoptの使い方

docoptはpythonスクリプトの上部にコメントとして使い方など必要事項を記述すると、docopt側で勝手にそのコメントを解析して、引数のオプションを取ってきてくれる優れものです。

文字で長々説明するよりも例を見せた方が早いと思うので、以下にdocoptのコメント部分の例を紹介します。

#!/usr/bin/python
"""
usage:
    test.py [-h|--help] [-b|--bbbbb] (-r <r_value>) [-o <o_value>] [-l <l_values>...]
options:
    -h,--help       show this help message and exit
    -b,--bbbbb      b option  (optional)
    -r <r_value>    r value   (required)
    -o <o_value>    o value   (optional) [default: 1.0]
    -l <l_values>   l values  (optional)
"""

このように、pythonスクリプトの上部にコメントとしてusage:とoptions:を記述します。

わざわざoptionをpythonの文法にしたがって記述するのではなく、このように人間がパッとみてもわかりやすいような形式で記述できるところがdocoptの魅力だと思います。

では、このコメント部のルールを以下に説明していきます。

 

docopt コメントのルール

基本的に使用できるオプションは

  • オプションの指定のみ( “-h” のような引数なしのオプション)
  • 引数を伴うオプション( “-n 3” のように引数を伴うオプション)
  • リストを伴うオプション( “-l hoge,fuga piyo” のようにリストをカンマ区切りで渡すオプション)

の3種類となります。また、引数の種類として、

  • 必須の引数
  • 任意の引数

を指定する事ができます。

使用できる記号一覧

( )オプションを記述する。カッコで囲まれたオプションは必須。
[ ]オプションを記述する。カッコで囲まれたオプションは任意。
|引数を並列して記述できる。[-a|–aaaaa]のようにロングオプションを併用する際に使用する。
< >引数を記述する。
引数がリスト形式である事を示す。< >の後に記述する。
[default: 1.0]Usageの欄に記述することで、デフォルト値を設定することができる。

 

コメントの解析

docoptでオプションを解析するためには以下のように記述します。

docopt(__doc__)

argsには辞書型で値が返されます。

例えば、戻り値を解析するためには以下のようにします。

args = docopt(__doc__)
if args['--bbbbb']:
    print( "option -b" )
if len( args['-r'] ):
    print( "option -r", args['-r'] )
if len( args['-o'] ):
    print( "option -r", args['-o'] )
if len( args['-l'] ):
    print( "option -l", args['-l'] )

 

docoptのサンプルコード

サンプルコードで動作を見てみましょう。

#!/usr/bin/python
"""
usage:
    test.py [-h|--help] [-b|--bbbbb] (-r <r_value>) [-o <o_value>] [-l <l_values>...]
options:
    -h,--help       show this help message and exit
    -b,--bbbbb      b option  (optional)
    -r <r_value>    r value   (required)
    -o <o_value>    o value   (optional) [default: 1.0]
    -l <l_values>   l values  (optional)
"""
from docopt import docopt
args = docopt(__doc__)     # 解析結果は辞書型で返ってくる
print( args )
args = docopt(__doc__)
if args['--bbbbb']:
    print( "option -b" )
if len( args['-r'] ):
    print( "option -r", args['-r'] )
if len( args['-o'] ):
    print( "option -o", args['-o'] )
if len( args['-l'] ):
    print( "option -l", args['-l'] )

 

例えば、上記のようなサンプルコード test.py を作成したとします。
このスクリプトに引数を渡して実行してみます。

$ python test.py -b -r hoge -l foo,bar

 

実行結果は以下のようになります。

{'--bbbbb': True,                       
 '--help': False,                       
 '-l': ['foo,bar'],
 '-o': '1.0',            
 '-r': 'hoge'}                          
option -b                                                                                                                                    
option -r hoge                                                                                                                               
option -o 1.0                                                                                                                                
option -l ['foo,bar'] 

引数のみのオプション(–bbbb,–help)はbool型で、
リスト形式の引数をとるオプション(-l)はちゃんとリスト形式で値が戻ってきています。

ちなみに、1文字のオプションとロングオプションを併用した場合は(今回の例では、-hと–help, -bと–bbbbb)、辞書型のキーはロングオプションで指定した文字列となることに注意が必要です。

 

引数が正しくなかった場合

ちなみに、-hを指定したり、必須オプション(-r)を記述しなかった場合にはusage:が表示されます。

 

例えば-oを指定して、引数を記述しなかった場合。

$ python test.py -r hoge -o

 

以下のように-oには引数が必要です。というメッセージとともにusage:が表示されます。

-o requires argument
usage:
    test.py [-h|--help] [-b|--bbbbb] (-r <r_value>) [-o <o_value>] [-l <l_values>...]

簡単ですね。

 

 

以上、docoptの使い方でした。