from optparse to argparse

なんであれ移行にはコストがかかります。
けれど、移行しないとみえてこないこともあります。

このargparse、Python2.7の時にチラ見して、「めんどくさー」とかになってしまい移行する意義をつかみ切れずにいたんだけど、
  スイッチ系オプションで'+'を使いたい、
とか言うしょうもなくもびみやうな理由でちょっと使ってみたら、目からウロコが超音速射出されたんで、散らばったウロコをひろいつつも備忘録

何が違うの

型変換&ヘルプ生成&コールバックとか、基本的にできることはoptparseとおんなじです。

  1. メソッドがadd_option -> add_argument とか微妙に違う(これはどうでもいいw)
  2. '-'以外をプリフィックスに使えるようになった(今回の主目的)
  3. options, remaindersというくくりではなく、明示的に「ここpositional args」とか全部指定するようになった(便利な半面めんどくさい)
  4. --version の扱いが変わった( add_argument()で自由にできるようになった)
  5. usageラインのoption表示を勝手に作ってくれるようになった(微妙)

やってみる

基本はoptparseといっしょ. まずは ArgumentParserを作って、それにメソッドで設定を追加して、んで parse_args().

目的のprefix change

いや単純

import argparse

parser = argparse.ArgumentParser(prefix_chars='-+')
parser.add_argument('-f', '--flag',
    action="store_false", dest="flag", default=None)
parser.add_argument("+f", '++flag',
    action="store_true", dest="flag")

args = parser.parse_args()
print args.flag

いやほんと簡単

tkuro@sawshark> python args.py
None
tkuro@sawshark> python args.py +f
True
tkuro@sawshark> python args.py -f
False

ちなみにこう言った同じdestにアクセスする奴の間でdefaultが違った場合は最初のモノが優先されるようです。

それ以外にも

位置依存引数は結構便利で、上手く使うとコマンドライン引数に限らず、何にでも使えそう。

import argparse
import sys

parser = argparse.ArgumentParser(add_help=False, prog="")

parser.add_argument("command", nargs=1,
    choices=["get", "put", "delete", "modify"],
    )
parser.add_argument("args", nargs='*', type=int)
parser.add_argument("-v", "--verbose", action="store_true", default=False)

for line in sys.stdin.readlines():
    try:
        args= parser.parse_args(line.split())
        print args
    except:
        pass

てな感じに書くだけでvalidation OK状態。

tkuro@sawshark> python command.py
get 10 20 30
delete 132 -v
modify 32 232 2 3 2 23 232

Namespace(args=[10, 20, 30], command=['get'], verbose=False)
Namespace(args=[132], command=['delete'], verbose=True)
Namespace(args=[32, 232, 2, 3, 2, 23, 232], command=['modify'], verbose=False)
tkuro@sawshark> python command.py
hoge

usage: [-v] {get,put,delete,modify} [args [args ...]]
: error: argument command: invalid choice: 'hoge' (choose from 'get', 'put', 'delete', 'modify')

おお。なんちゃってコンフィグファイルにもつかえそうな感じ。
面白いのでなんかしらまた追加するかも

結論

非常に柔軟。フルスペックパーサとoptparseの間を埋めるような存在で、応用範囲が広そうです。まあそこまでせんでも・・・という向きにはoptparseのままでもいいのかもだし、まだまだoptparseもサポートされるわけだけれけど、こういった微妙な差とかって結構間違いのもとで時間食いなので、確実に2.6以前を使わない、って人はこちらにパラダイムシフトしておいたほうが後々嬉しい気がします。