docopt

PyCon UK 2012の動画を見てたら面白いもの見つけたのでメモ。

docoptというもので、コマンドラインツールを作るときに、docstringを解析して引数をパースしてくれる優れもの。
http://docopt.org/

docstringのUsageセクションに用例を書いておくとそれを解析してくれる。例えば、

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Test

Usage:
    test ship new <name>
    test ship <name> move <x> <y> [--speed=<kn>]
    test ship <name> (<from> <to>)...
    test ship shoot <x> <y>
    test mine (set|remove) <x> <y> [--moored|--drifting]
    test -h | --help
    test --version
Options:
    -h --help       Show this screen.
    --version       Show version.
    --speed=<kn>    Speed in knots [default: 10].
    --moored        Moored mine.
    --drifting      Drifting mine.

"""

from docopt import docopt

print docopt(__doc__, version="0.1.0")

を実行すると

% ./test ship new hoge
{'--drifting': False,
 '--help': 0,
 '--moored': False,
 '--speed': '10',
 '--version': 0,
 '.': False,
 '10': False,
 '<from>': [],
 '<name>': 'pig',
 '<to>': [],
 '<x>': None,
 '<y>': None,
 'Drifting': False,
 'Moored': False,
 'Options:': False,
 'Show': 0,
 'Speed': False,
 'default:': False,
 'in': False,
 'knots': False,
 'mine': False,
 'mine.': 0,
 'move': False,
 'new': True,
 'remove': False,
 'screen.': False,
 'set': False,
 'ship': True,
 'shoot': False,
 'this': False,
 'version.': False}

みたいにディクショナリを返してくれる。

間違った使い方をして、解析できなかったら、docstringを表示する

% ./test sleep
Usage:
    test ship new <name>
    test ship <name> move <x> <y> [--speed=<kn>]
    test ship <name> (<from> <to>)...
    test ship shoot <x> <y>
    test mine (set|remove) <x> <y> [--moored|--drifting]
    test -h | --help
    test --version
Options:
    -h --help       Show this screen.
    --version       Show version.
    --speed=<kn>    Speed in knots [default: 10].
    --moored        Moored mine.
    --drifting      Drifting mine.

便利っぽいですね。

簡単に表記について説明すると、

  • "< >" で囲んだものは、必須の引数とみなす。上で言うと、ship の後ろの は必須だから、指定しないとdocscringを表示する。
  • "[ ]" で囲んだものは、任意の引数とみなす。上で言うと、--speed とかは指定しなくても良い。
  • "( )" はグルーピングするために使う。上で言うと、from と to を両方指定しないといけない。
  • "..." は前の引数を複数個指定するときに使う。上で言うと、from と to のペアを複数個指定することが出来る。
  • "[default: val]" を、Optionsセクションで指定すると、任意の引数にデフォルト値を設定することが出来る。上で言うと、--speed を省略した時に、デフォルト値の10が返される。

という感じ。それからオプションにはショートオプション( "-" )とロングオプション( "--" )があって、ショートオプションは連続指定できる。例えば、"-abc" は "-a -b -c" と等価に扱われる。

API

docopt(doc, argv=None, help=True, version=None, options_first=False)

だけ。

  • argv は、引数のリストで、デフォルトで sys.argv[1:] が渡される。
  • help は、False にすると、-h あるいは --help に手動で対応できる。デフォルトでは True で、docstring を表示して終了する。
  • version は、--version が渡された時に表示するバージョンを指定できる。
  • options_first は、True にすると、最初にオプションの指定をすることを強制できる。というか後ろに渡された場合は必須引数とみなされる。

詳しい説明は、http://docopt.org/ へ。Rubyとかの実装もあるらしい。